--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/loggingservices/eventlogger/test/src/t_loghicaphelper.cpp Fri Jan 22 11:06:30 2010 +0200
@@ -0,0 +1,724 @@
+// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Platform security prohibits the existing logeng tests from doing
+// direct operations on data-caged files. Giving the tests a higher
+// capability might mask other errors. Therefore any file manipulation
+// may be sub-contracted to this process as needed.
+//
+//
+
+
+#include <s32file.h>
+#include <babackup.h>
+#include <bautils.h>
+#include <barsc.h>
+#include <logserv.rsg>
+#include "TEST.H"
+
+const TUid KTestEventUid = {0x10005393};
+_LIT(KTestEventDesc1, "Event Type Description");
+_LIT(KTestDirection1, "Direction");
+_LIT(KTestStatus1, "Status");
+_LIT(KTestStatus2, "Changed Status");
+_LIT(KTestNumber1, "Number");
+const TLogContactItemId KTestContact1 = 0x1234;
+const TLogContactItemId KTestContact2 = 0x1234567;
+_LIT(KTestRemote1, "Remote Test 1");
+_LIT(KTestRemote2, "Remote Test 2");
+_LIT(KTestRemote3, "Remote Test 3");
+_LIT(KTestStatusT3, "Status Test 3");
+_LIT(KTestEventDesc, "Test Event");
+
+_LIT(KLogEngPrivatePath, "c:\\private\\101f401d\\");
+
+_LIT(KLogHiCapHelperPanic, "TLHCHlpr");
+
+RFs theFs;
+CActiveScheduler *TheTestScheduler = NULL;
+
+//===========================================================================================
+
+static TPtrC FileName(const TText* aFile)
+ {
+ TPtrC p(aFile);
+ TInt ix=p.LocateReverse('\\');
+ if (ix<0)
+ ix=p.LocateReverse('/');
+ if (ix>=0)
+ p.Set(p.Mid(1+ix));
+ return p;
+ }
+
+void LogLeave(TInt aErr, const TText* aFile, TInt aLine)
+ {
+ TPtrC fname(FileName(aFile));
+ RDebug::Print(_L("*** LogEng test leave, err=%d, file: %S-%d\r\n"), aErr, &fname, aLine);
+ User::Leave(aErr);
+ }
+
+#undef TEST_STRING
+#define TEST_STRING(s) _S(s)
+
+#undef LEAVE
+#undef LEAVE_IF_ERROR
+#define LEAVE(err) LogLeave(err, TEST_STRING(__FILE__), __LINE__)
+#define LEAVE_IF_ERROR(err) (err < KErrNone ? LogLeave(err, TEST_STRING(__FILE__), __LINE__) : void(0))
+
+//===========================================================================================
+
+//Supported remote operaions
+enum THelperOp
+ {
+ EOpNotDefined,
+ EDeleteDatabase1,
+ EDeleteDatabase2,
+ EIsDatabaseOpen,
+ EDatabaseSize,
+ ECopyCorruptDbFile,
+ ECopyCorruptDamagedDbFile,
+ ECopyOldDbFile,
+ EAddEvent,
+ EAddTestEvents,
+ EAddEventType,
+ EInvalidSchema,
+ EIsMatchingEnabled
+ } ;
+
+_LIT(KOldCorruptDatabase,"z:\\system\\data\\corruptLogdbu.dat");
+_LIT(KOldCorruptDamagedDatabase,"z:\\system\\data\\corruptDamagedLogdbu.dat");
+_LIT(KOldFormatDatabase,"z:\\system\\data\\oldLogdbu.dat");
+
+
+CTestActive::CTestActive(TInt aPriority)
+: CActive(aPriority)
+ {
+ CActiveScheduler::Add(this);
+ iDelayTime=0;
+ }
+
+CTestActive::~CTestActive()
+ {
+ Cancel();
+ }
+
+void CTestActive::DoCancel()
+ {
+ TRequestStatus* s=&iStatus;
+ User::RequestComplete(s, KErrNone);
+ }
+
+void CTestActive::StartL()
+ {
+ iDelayCompletion=EFalse;
+ iDelayTime=0;
+ iStatus = KRequestPending;
+ SetActive();
+ }
+
+void CTestActive::StartL(TInt aDelay)
+ {
+ iDelayCompletion=ETrue;
+ iDelayTime=aDelay;
+ iStatus = KRequestPending;
+ SetActive();
+ }
+
+void CTestActive::RunL()
+ {
+ if(iDelayCompletion && iDelayTime)
+ {
+ // Wait for events in other threads to have a go....
+ User::After(iDelayTime);
+ iDelayTime=0;
+ iStoredStatus=iStatus;
+ SetActive();
+ TRequestStatus* s=&iStatus;
+ User::RequestComplete(s, KErrNone);
+ }
+ else
+ {
+ if(iDelayCompletion)
+ iStatus=iStoredStatus;
+
+ LOGTEXT("CTestActive::RunL() - Stopping the scheduler");
+ CActiveScheduler::Stop();
+ }
+ }
+
+//.................................................................................................
+
+//See TestUtils::TestInvalidSchemaL(). Re-creates the LogEng database and checkes whether a new
+//LogEng connection can be established (by creating a CLogClient object).
+static void TestInvalidSchemaL()
+ {
+ TheTestScheduler = new (ELeave) CActiveScheduler;
+ CleanupStack::PushL( TheTestScheduler );
+ CActiveScheduler::Install( TheTestScheduler );
+
+ //Reseting of log engine databse is done via its backup server. This seems a
+ //bit odd. Perhaps write a CLogClient API that does it?
+ //Create backup session wrapper
+ CBaBackupSessionWrapper* backup = CBaBackupSessionWrapper::NewL();
+ CleanupStack::PushL(backup);
+
+ //This eventually calls CLogBackup::ChangeFileLockL(..) which closes the database
+ //file and notifies all handles to that file that it has closed.
+ backup->CloseFileL(KLogDatabaseName, MBackupObserver::EReleaseLockNoAccess);
+ User::After(1000000);
+
+ //Since the log engine database file is closed we can replace it.
+ //Once this file is deleted, the backup server notices this and attempts to reopen
+ //the database. Since the file is deleted a default database is created instead.
+ RDbNamedDatabase database;
+ TInt err = database.Replace(theFs, KLogDatabaseName);
+ database.Close();
+ LEAVE_IF_ERROR(err);
+
+ // The following will leave if there is a problem
+ CLogClient* client = CLogClient::NewL(theFs);
+ delete client;
+
+ CleanupStack::PopAndDestroy(2); // scheduler + backup
+ TheTestScheduler = NULL;
+ }
+
+//.................................................................................................
+
+//See TestUtils::AddEventTypeL(). Adds an event type to the LogEng database.
+static void AddEventTypeL()
+ {
+ TheTestScheduler = new (ELeave) CActiveScheduler;
+ CleanupStack::PushL(TheTestScheduler);
+ CActiveScheduler::Install(TheTestScheduler);
+
+ CLogClient* client = CLogClient::NewL(theFs);
+ CleanupStack::PushL(client);
+
+ CTestActive* active = new(ELeave)CTestActive();
+ CleanupStack::PushL(active);
+
+ CLogEventType* type = CLogEventType::NewL();
+ CleanupStack::PushL(type);
+
+ type->SetUid(KTestEventUid);
+ type->SetDescription(KTestEventDesc1);
+ type->SetLoggingEnabled(ETrue);
+
+ client->AddEventType(*type, active->iStatus);
+
+ active->StartL();
+ CActiveScheduler::Start();
+ LEAVE_IF_ERROR(active->iStatus.Int());
+
+ CleanupStack::PopAndDestroy(4); // scheduler, client, active, type
+ TheTestScheduler = NULL;
+ }
+
+//.................................................................................................
+
+//See TestUtils::AddViewTestEventsL(). Adds events to the LogEng database.
+static void AddTestEventsL()
+ {
+ TheTestScheduler = new (ELeave) CActiveScheduler;
+ CleanupStack::PushL(TheTestScheduler);
+ CActiveScheduler::Install(TheTestScheduler);
+
+ CTestActive* active = new(ELeave)CTestActive;
+ CleanupStack::PushL(active);
+
+ CLogClient* client = CLogClient::NewL(theFs);
+ CleanupStack::PushL(client);
+
+ TLogString direction;
+ client->GetString(direction, R_LOG_DIR_IN);
+
+ // Create a test event type
+ CLogEventType* type = CLogEventType::NewL();
+ CleanupStack::PushL(type);
+ type->SetUid(KTestEventUid);
+ type->SetDescription(KTestEventDesc);
+ type->SetLoggingEnabled(ETrue);
+
+ // Register the event type
+ active->StartL();
+ client->AddEventType(*type, active->iStatus);
+ CActiveScheduler::Start();
+ LEAVE_IF_ERROR(active->iStatus.Int());
+
+ // Now add some events...
+ //
+ CLogEvent* event = CLogEvent::NewL();
+ CleanupStack::PushL(event);
+ //
+ event->SetEventType(KLogCallEventTypeUid);
+ event->SetContact(KTestContact1);
+ event->SetDirection(direction);
+ event->SetDurationType(KLogDurationValid);
+ event->SetNumber(KTestNumber1);
+ event->SetRemoteParty(KTestRemote1);
+ event->SetStatus(KTestStatus1);
+
+ // Add event
+ active->StartL();
+ client->AddEvent(*event, active->iStatus);
+ CActiveScheduler::Start();
+ LEAVE_IF_ERROR(active->iStatus.Int());
+ //
+
+ event->SetEventType(KTestEventUid); // low cap visible
+ event->SetContact(KTestContact1);
+ event->SetDirection(direction);
+ event->SetDurationType(KLogDurationNone);
+ event->SetNumber(KTestNumber1);
+ event->SetRemoteParty(KTestRemote1);
+ event->SetStatus(KTestStatus1);
+
+ // Add event
+ active->StartL();
+ client->AddEvent(*event, active->iStatus);
+ CActiveScheduler::Start();
+ LEAVE_IF_ERROR(active->iStatus.Int());
+ //
+
+ event->SetEventType(KLogCallEventTypeUid);
+ event->SetContact(KTestContact2);
+ event->SetDirection(direction);
+ event->SetDurationType(KLogDurationValid);
+ event->SetNumber(KTestNumber1);
+ event->SetRemoteParty(KTestRemote2);
+ event->SetStatus(KTestStatus2);
+
+ // Add event and 4 duplicates
+ for(TInt i=0; i<5; i++)
+ {
+ active->StartL();
+ client->AddEvent(*event, active->iStatus);
+ CActiveScheduler::Start();
+ LEAVE_IF_ERROR(active->iStatus.Int());
+ }
+
+ event->SetEventType(KTestEventUid); // low cap visible
+ event->SetContact(KTestContact2);
+ event->SetDirection(KTestDirection1);
+ event->SetDurationType(KLogDurationData);
+ event->SetNumber(KTestNumber1);
+ event->SetRemoteParty(KTestRemote3);
+ event->SetStatus(KTestStatusT3);
+
+ // Add event
+ active->StartL();
+ client->AddEvent(*event, active->iStatus);
+ CActiveScheduler::Start();
+ LEAVE_IF_ERROR(active->iStatus.Int());
+
+ CleanupStack::PopAndDestroy(5); // event, client, type, active, scheduler
+ TheTestScheduler = NULL;
+ }
+
+//.................................................................................................
+
+//See TestUtils::AddEventL(). Adds an event to the LogEng database.
+//The event type is set to be: KLogCallEventTypeUid.
+//Return: the Id of the added event
+static TInt AddEventL()
+ {
+ TheTestScheduler = new (ELeave) CActiveScheduler;
+ CleanupStack::PushL(TheTestScheduler);
+ CActiveScheduler::Install(TheTestScheduler);
+
+ CLogClient* client = CLogClient::NewL(theFs);
+ CleanupStack::PushL(client);
+
+ CTestActive* active = new(ELeave)CTestActive();
+ CleanupStack::PushL(active);
+
+ CLogEvent* event = CLogEvent::NewL();
+ CleanupStack::PushL(event);
+
+ event->SetEventType(KLogCallEventTypeUid);
+
+ active->StartL();
+ client->AddEvent(*event, active->iStatus);
+ CActiveScheduler::Start();
+ LEAVE_IF_ERROR(active->iStatus.Int());
+ TLogId eventId = event->Id();
+
+ CleanupStack::PopAndDestroy(4); // scheduler, client, active, event
+ TheTestScheduler = NULL;
+ return eventId;
+ }
+
+//.................................................................................................
+
+#ifdef _DEBUG
+static void StopLogServerL()
+ {
+ static RLogTestSession logServSession;
+ //this function doesn't have any effect on UREL builds as LogEng server doesn't
+ //support the transient mode in UREL builds
+ //Used for LogEng server side heap failure testing.
+ TInt error = KErrNone;
+
+ if(!logServSession.Handle())
+ {
+ error = logServSession.Connect();
+ }
+
+ // Is the server running?
+ if(error == KErrNotFound)
+ {
+ return;
+ }
+ LEAVE_IF_ERROR(error);
+
+ // Make the server transient
+ TInt p0 = 1;
+ TIpcArgs ipcArgs(p0);
+ LEAVE_IF_ERROR(logServSession.Send(ELogMakeTransient, ipcArgs));
+
+ logServSession.Close();
+
+ User::After(6 * 1000000); // Enough time for the server to exit
+ }
+#else//_DEBUG
+static void StopLogServerL()
+ {
+ RDebug::Print(_L("StopLogServerL(): the LogEng server cannot be stopped in release mode. ELogMakeTransient is a debug message.\n"));
+ }
+#endif//_DEBUG
+
+//.................................................................................................
+
+static void DoDeleteDatabaseL(const TDesC& aDbPath, TBool aCloseBeforeDelete)
+ {
+ CBaBackupSessionWrapper* backup = NULL;
+ if(aCloseBeforeDelete)
+ {
+ //Reseting of log engine databse is done via its backup server.
+ //Create backup session wrapper
+ backup = CBaBackupSessionWrapper::NewL();
+ CleanupStack::PushL(backup);
+
+ //This eventually calls CLogBackup::ChangeFileLockL(..) which closes the database
+ //file and notifies all handles to that file that it has closed.
+ backup->CloseFileL(aDbPath, MBackupObserver::EReleaseLockNoAccess);
+ User::After(1000000);
+ }
+
+ //Since the log engine database file is closed we can delete it.
+ //Once this file is deleted, the backup server notices this and attempts to reopen
+ //the database. Since the file is deleted a default database is created instead.
+
+ TInt error = theFs.Delete(aDbPath);
+
+ if(!(error == KErrNone || error == KErrNotFound || error == KErrPathNotFound) )
+ {
+ RDebug::Print(_L("DoDeleteDatabaseL(), Error %d deleting database \"%S\"\n"),error, &aDbPath);
+ }
+ else
+ {
+ RDebug::Print(_L("DoDeleteDatabaseL(), Database \"%S\" deleted ok\n"), &aDbPath);
+ }
+
+ if(aCloseBeforeDelete)
+ {
+ //The next line restarts the logeng server and re-creates logdbu.dat file.
+ CleanupStack::PopAndDestroy(backup);
+
+ TInt count = 10;
+ while(count--)
+ {
+ User::After(100000);
+ TEntry entry;
+ if(theFs.Entry(aDbPath, entry) == KErrNone)
+ {
+ break;
+ }
+ }
+ }
+ }
+
+//See TestUtils::DeleteDatabaseL().
+//If "aCloseBeforeDelete" is true then re-create the LogEng database.
+static void DeleteDatabaseL(TBool aCloseBeforeDelete)
+ {
+ RDebug::Print(_L("DeleteDatabaseL(), Deleting database \"%S\"\r\n"), &KLogDatabaseName);
+
+ TRAPD(err, DoDeleteDatabaseL(KLogDatabaseName, aCloseBeforeDelete));
+ if(err == KErrNotFound || err == KErrPathNotFound)
+ {
+ err = KErrNone;
+ }
+ LEAVE_IF_ERROR(err);
+ }
+
+//.................................................................................................
+
+//See TestUtils::CopyCorruptDbL().
+//See TestUtils::CopyOldDbL().
+//See TestUtils::CopyCorruptDamagedDbL()
+//
+//The LogEng database will be replaced with a the database which name is passed as a parameter (for testing purposes).
+//The LogEng server will be stopped.
+//This call works only in debug mode.
+static void CopyDatabaseL(const TDesC& aNewDatabase)
+ {
+ StopLogServerL();
+
+ CFileMan* fileMan=CFileMan::NewL(theFs);
+ CleanupStack::PushL(fileMan);
+
+ DeleteDatabaseL(ETrue); // it won't be replaced as the server has stopped
+
+ TInt err = fileMan->Copy(aNewDatabase, KLogDatabaseName);
+ if(err != KErrNone)
+ {
+ // Note this only works on textshell ROMs, techview ROMs fail here with KErrInUse (-14)
+ RDebug::Print(_L("CopyDatabaseL(), File copy \"%S\" to \"%S\", err=%d\n"), &aNewDatabase, &KLogDatabaseName, err);
+ LEAVE(err);
+ }
+ // files copied are sometimes read-only, so make read-write
+ err = theFs.SetAtt(KLogDatabaseName, 0, KEntryAttReadOnly);
+ if(err != KErrNone)
+ {
+ RDebug::Print(_L("CopyDatabaseL(), Set \"%S\" file attributes err=%d\n"), &KLogDatabaseName, err);
+ LEAVE(err);
+ }
+
+ CleanupStack::PopAndDestroy(); // fileMan
+ }
+
+//.................................................................................................
+
+//See TestUtils::DatabaseSizeL().
+//Returns the LogEng database size.
+static TInt DatabaseSizeL()
+ {
+ TEntry file;
+ LEAVE_IF_ERROR(theFs.Entry(KLogDatabaseName, file));
+ return file.iSize;
+ }
+
+//.................................................................................................
+
+static void Initialize(const TDesC& aName)
+ {
+ User::RenameThread(aName);
+ }
+
+//.................................................................................................
+
+//See TestUtils::IsDatabaseOpenL().
+//Returns whether the LogEng database is open or not.
+static TBool DatabaseIsOpenL()
+ {
+ TBool answer;
+ LEAVE_IF_ERROR(theFs.IsFileOpen(KLogDatabaseName, answer));
+ return answer;
+ }
+
+//.................................................................................................
+
+//See TestUtils::MatchingEnabledL().
+//The function opens the LogEng server resource file (logserv.rsc) and gets the value of
+//r_log_contact_match_count resource. This value will be retured as a result of the call.
+//If the value is 0 - "contacts matching" part of the test will be skipped.
+static TBool MatchingEnabledL()
+ {
+ // Get language of resource file
+ _LIT(KLogResourceFile,"z:\\private\\101f401d\\logserv.rsc");
+ TFileName fileName(KLogResourceFile);
+ BaflUtils::NearestLanguageFile(theFs, fileName);
+
+ // Open resource file
+ RResourceFile res;
+ res.OpenL(theFs, fileName);
+ HBufC8* buf = res.AllocReadLC(R_LOG_CONTACT_MATCH_COUNT);
+ res.Close();
+
+ TResourceReader reader;
+ reader.SetBuffer(buf);
+
+ TBool enabled = reader.ReadInt16() > 0;
+ CleanupStack::PopAndDestroy(buf);
+ return enabled;
+ }
+
+//.................................................................................................
+
+static TInt DoTaskL(THelperOp aOperation)
+ {
+ TInt rc = KErrNone;
+ switch(aOperation)
+ {
+ case EDeleteDatabase1:
+ DeleteDatabaseL(ETrue);
+ break;
+ case EDeleteDatabase2:
+ DeleteDatabaseL(EFalse);
+ break;
+ case EIsDatabaseOpen:
+ rc = DatabaseIsOpenL();
+ break;
+ case EDatabaseSize:
+ rc = DatabaseSizeL();
+ break;
+ case ECopyCorruptDbFile:
+ CopyDatabaseL(KOldCorruptDatabase);
+ break;
+ case ECopyCorruptDamagedDbFile:
+ CopyDatabaseL(KOldCorruptDamagedDatabase);
+ break;
+ case ECopyOldDbFile:
+ CopyDatabaseL(KOldFormatDatabase);
+ break;
+ case EAddEvent:
+ rc = AddEventL();
+ break;
+ case EAddTestEvents:
+ AddTestEventsL();
+ break;
+ case EAddEventType:
+ AddEventTypeL();
+ break;
+ case EInvalidSchema:
+ TestInvalidSchemaL();
+ break;
+ case EIsMatchingEnabled:
+ rc = MatchingEnabledL();
+ break;
+ default:
+ rc = KErrNone; // go away quietly
+ break;
+ }
+ LEAVE_IF_ERROR(rc);
+ return rc;
+ }
+
+//.................................................................................................
+
+static THelperOp TaskType(const TDesC& aCmdLine)
+ {
+ THelperOp task = EOpNotDefined;
+
+ if(aCmdLine.CompareF(_L("-delete_db1")) == 0)
+ {
+ task = EDeleteDatabase1;
+ }
+ else if(aCmdLine.CompareF(_L("-delete_db2")) == 0)
+ {
+ task = EDeleteDatabase2;
+ }
+ else if(aCmdLine.CompareF(_L("-db_is_open")) == 0)
+ {
+ task = EIsDatabaseOpen;
+ }
+ else if(aCmdLine.CompareF(_L("-db_size")) == 0)
+ {
+ task = EDatabaseSize;
+ }
+ else if(aCmdLine.CompareF(_L("-copy_corrupt")) == 0)
+ {
+ task = ECopyCorruptDbFile;
+ }
+ else if(aCmdLine.CompareF(_L("-copy_corrupt_damaged")) == 0)
+ {
+ task = ECopyCorruptDamagedDbFile;
+ }
+ else if(aCmdLine.CompareF(_L("-copy_old")) == 0)
+ {
+ task = ECopyOldDbFile;
+ }
+ else if(aCmdLine.CompareF(_L("-add_event")) == 0)
+ {
+ task = EAddEvent;
+ }
+ else if(aCmdLine.CompareF(_L("-add_view_test_events")) == 0)
+ {
+ task = EAddTestEvents;
+ }
+ else if(aCmdLine.CompareF(_L("-add_event_type")) == 0)
+ {
+ task = EAddEventType;
+ }
+ else if(aCmdLine.CompareF(_L("-invalid_schema")) == 0)
+ {
+ task = EInvalidSchema;
+ }
+ else if(aCmdLine.CompareF(_L("-is_matching_enabled")) == 0)
+ {
+ task = EIsMatchingEnabled;
+ }
+ else
+ {
+ RDebug::Print(_L("** t_logHiCapHelper, ** Bad command line argument: %S\r\n"), &aCmdLine);
+ User::Panic(KLogHiCapHelperPanic, KErrArgument);
+ }
+ return task;
+ }
+
+static TInt EnvCreate()
+ {
+ TInt err = theFs.Connect();
+ if(err == KErrNone)
+ {
+ err = theFs.MkDirAll(KLogEngPrivatePath);
+ if(err == KErrAlreadyExists)
+ {
+ err = KErrNone;
+ }
+ }
+ if(err != KErrNone)
+ {
+ RDebug::Print(_L("** t_logHiCapHelper, error %d creating test environment\r\n"), err);
+ }
+ return err;
+ }
+
+TInt E32Main()
+ {
+ __UHEAP_MARK;
+
+ Initialize(_L("T_HICAPHELPER"));
+
+ CTrapCleanup* tc = CTrapCleanup::New();
+ if(!tc)
+ {
+ User::Panic(KLogHiCapHelperPanic, KErrNoMemory);
+ }
+
+ TBuf<64> cmdLine;
+ User::CommandLine(cmdLine);
+ THelperOp task = TaskType(cmdLine);
+
+ TInt rc = 0;
+ TInt err = EnvCreate();
+ if(err == KErrNone)
+ {
+ TRAP(err, rc = DoTaskL(task));
+ if(err < 0)
+ {
+ rc = err;
+ RDebug::Print(_L("** t_logHiCapHelper, DoTaskL(), Task %d, Error %d\n"), task, rc);
+ }
+ }
+
+ theFs.Close();
+ delete tc;
+
+ __UHEAP_MARKEND;
+
+ return rc;
+ }
+