diff -r cd501b96611d -r ece3df019add authenticationservices/authenticationserver/test/tauthdb/step_persist2.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/authenticationservices/authenticationserver/test/tauthdb/step_persist2.cpp Tue Nov 24 09:06:03 2009 +0200 @@ -0,0 +1,595 @@ +/* +* 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 the License "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: +* +*/ + + +#include +#include "tauthdbstep.h" +#include + +using namespace AuthServer; + +const TIdentityId KIdentity1Id = 'I1ID'; +const TIdentityId KIdentity2Id = 'I2ID'; +const TIdentityId KIdentity3Id = 'I3ID'; +_LIT(KIdentity1Desc, "identity-1-desc"); +_LIT(KIdentity1DescB, "identity-1-descB"); +_LIT(KIdentity2Desc, "identity-2-desc"); +_LIT(KIdentity3Desc, "identity-3-desc"); + +const TPluginId KPlugin1Id = 'PID1'; +const TPluginId KPlugin2Id = 'PID2'; +const TPluginId KPlugin3Id = 'PID3'; +const TPluginId KPlugin4Id = 'PID4'; +const TPluginId KPluginAId = 'PIDA'; +const TPluginId KPluginBId = 'PIDB'; + + +CTStepPersist2::CTStepPersist2() + { + SetTestStepName(KTStepCreateTestDb); + } + + +TVerdict CTStepPersist2::doTestStepL() + { + __UHEAP_MARK; + + RemoveExistingDbL(); + + TestOpenCloseL(); + TestIdentitiesL(); + TestPrefsL(); + TestTrainedPluginsL(); + TestTrainingStatusL(); + TestRepairL(); + TestCompressL(); + + __UHEAP_MARKEND; + return EPass; + } + + +void CTStepPersist2::TestOpenCloseL() +/** + Test simply opening and closing a database, + without using any other operations. + */ + { + CAuthDb2* db = CAuthDb2::NewL(iFs); + delete db; + } + + +void CTStepPersist2::TestIdentitiesL() + { + TInt r; + + __UHEAP_MARK; + RemoveExistingDbL(); + CAuthDb2* db = CAuthDb2::NewLC(iFs); + + RArray ids; + + // get id list before any ids defined + ids.AppendL('SYMB'); // garbage; ensure removed + db->IdentitiesL(ids); + TESTL(ids.Count() == 0); + + // add an identity + db->AddIdentityL(KIdentity1Id, KIdentity1Desc); + db->IdentitiesL(ids); + TESTL(ids.Count() == 1); + TESTL(ids[0] == KIdentity1Id); + + // retrieve the identity's description + TestDescriptionL(db, KIdentity1Id, KIdentity1Desc); + + // change the identity's description + db->SetDescriptionL(KIdentity1Id, KIdentity1DescB); + TestDescriptionL(db, KIdentity1Id, KIdentity1DescB); + + // change the identity's description to a string which is + // too long; ensure fails. + TBuf dbuf; + dbuf.Fill('a', KMaxDescLen - 1); // limit - 1 + db->SetDescriptionL(KIdentity1Id, dbuf); + TestDescriptionL(db, KIdentity1Id, dbuf); + + dbuf.Fill('a', KMaxDescLen); // limit + db->SetDescriptionL(KIdentity1Id, dbuf); + TestDescriptionL(db, KIdentity1Id, dbuf); + + db->SetDescriptionL(KIdentity1Id, KIdentity1DescB); + TestDescriptionL(db, KIdentity1Id, KIdentity1DescB); + dbuf.Fill('a', KMaxDescLen + 1); // limit + 1 + TRAP(r, db->SetDescriptionL(KIdentity1Id, dbuf)); + TESTL(r == KErrAuthServDescTooLong); + TestDescriptionL(db, KIdentity1Id, KIdentity1DescB); // keep old desc + + // add a second identity + db->AddIdentityL(KIdentity2Id, KIdentity2Desc); + db->IdentitiesL(ids); + TESTL(ids.Count() == 2); + TESTL( (ids[0] == KIdentity1Id && ids[1] == KIdentity2Id) + || (ids[0] == KIdentity2Id && ids[1] == KIdentity1Id) ); + TestDescriptionL(db, KIdentity1Id, KIdentity1DescB); + TestDescriptionL(db, KIdentity2Id, KIdentity2Desc); + + // add an identity which already exists + TRAP(r, db->AddIdentityL(KIdentity2Id, KIdentity2Desc)); + TESTL(r == KErrAuthServIdentityAlreadyExists); + + // retrieve description for an unregistered identity + TRAP(r, db->DescriptionL(KIdentity3Id)); + TESTL(r == KErrAuthServIdentityNotFound); + + // set description for an unregistered identity + TRAP(r, db->SetDescriptionL(KIdentity3Id, KIdentity3Desc)); + TESTL(r == KErrAuthServIdentityNotFound); + + // remove an unregistered identity + TRAP(r, db->RemoveIdentityL(KIdentity3Id)); + TESTL(r == KErrAuthServIdentityNotFound); + + // remove an identity + db->RemoveIdentityL(KIdentity1Id); + db->IdentitiesL(ids); + TESTL(ids.Count() == 1); + TESTL(ids[0] == KIdentity2Id); + TestDescriptionL(db, KIdentity2Id, KIdentity2Desc); + + // remove the last identity + db->RemoveIdentityL(KIdentity2Id); + db->IdentitiesL(ids); + TESTL(ids.Count() == 0); + + // create an identity with a description to a string which is + // too long; ensure fails. + dbuf.Fill('a', KMaxDescLen - 1); // limit - 1 + db->AddIdentityL(KIdentity3Id, dbuf); + TestDescriptionL(db, KIdentity3Id, dbuf); + db->RemoveIdentityL(KIdentity3Id); + + dbuf.Fill('a', KMaxDescLen); // limit + db->AddIdentityL(KIdentity3Id, dbuf); + TestDescriptionL(db, KIdentity3Id, dbuf); + db->RemoveIdentityL(KIdentity3Id); + + dbuf.Fill('a', KMaxDescLen + 1); // limit + 1 + TRAP(r, db->AddIdentityL(KIdentity3Id, dbuf)); + TESTL(r == KErrAuthServDescTooLong); + db->IdentitiesL(ids); // no identity created + TESTL(ids.Count() == 0); + + CleanupStack::PopAndDestroy(db); + __UHEAP_MARKEND; + } + +void CTStepPersist2::TestDescriptionL( + CAuthDb2* aDb, TIdentityId aIdentityId, const TDesC& aExpDesc) +/** + Helper function for TestIdentitiesL. Ensures the + supplied identity has the supplied description. + + @param aDb Database which contains the identity. + @param aIdentity Identity whose description should be + retrieved. + @param aDesc Expected description. + */ + { + HBufC* desc = aDb->DescriptionL(aIdentityId); + CleanupStack::PushL(desc); + TESTL(*desc == aExpDesc); + CleanupStack::PopAndDestroy(desc); + } + + +void CTStepPersist2::TestPrefsL() +/** + Tests adding, modifying, and removing + preferences from the database. + */ + { + TPluginId prefId; + __UHEAP_MARK; + + RemoveExistingDbL(); + CAuthDb2* db = CAuthDb2::NewLC(iFs); + + // get a preferred plugin for a type with no preferred plugin + prefId = db->PreferredPluginL(EAuthBiometric); + TESTL(prefId == KUnknownPluginId); + + // set a type's preferred plugin + db->SetPreferredPluginL(EAuthBiometric, KPlugin1Id); + prefId = db->PreferredPluginL(EAuthBiometric); + TESTL(prefId == KPlugin1Id); + + // change a type's preferred plugin + db->SetPreferredPluginL(EAuthBiometric, KPlugin2Id); + prefId = db->PreferredPluginL(EAuthBiometric); + TESTL(prefId == KPlugin2Id); + + // clear a type's preferred plugin + db->ClearPreferredPluginL(EAuthBiometric); + prefId = db->PreferredPluginL(EAuthBiometric); + TESTL(prefId == KUnknownPluginId); + + // set preferred plugin for more than one type + db->SetPreferredPluginL(EAuthBiometric, KPlugin3Id); + db->SetPreferredPluginL(EAuthKnowledge, KPlugin4Id); + prefId = db->PreferredPluginL(EAuthBiometric); + TESTL(prefId == KPlugin3Id); + prefId = db->PreferredPluginL(EAuthKnowledge); + TESTL(prefId == KPlugin4Id); + + CleanupStack::PopAndDestroy(db); + + __UHEAP_MARKEND; + } + + +void CTStepPersist2::TestTrainedPluginsL() +/** + Test adding and removing trained plugins. + */ + { + __UHEAP_MARK; + + TInt r; + RemoveExistingDbL(); + CAuthDb2* db = CAuthDb2::NewLC(iFs); + + const CTransientKeyInfo& tkiA = *iId1Keys[0]; + const CTransientKeyInfo& tkiB = *iId1Keys[1]; + const CTransientKeyInfo& tkiC = *iId1Keys[2]; + + // set key info for an unregistered identity + TRAP(r, db->SetTrainedPluginL(KIdentity1Id, KPluginAId, tkiA)); + TESTL(r == KErrAuthServIdentityNotFound); + + // set key info for a registered identity + db->AddIdentityL(KIdentity1Id, KIdentity1Desc); + db->SetTrainedPluginL(KIdentity1Id, KPluginAId, tkiA); + + // get key info for a trained identity + TestKeyPresentL(db, KIdentity1Id, KPluginAId, tkiA); + + // change key info for a trained identity + db->SetTrainedPluginL(KIdentity1Id, KPluginAId, tkiB); + TestKeyPresentL(db, KIdentity1Id, KPluginAId, tkiB); + + // ---- bad KeyInfoL args ---- + + // get key info for registered identity but untrained plugin + TRAP(r, db->KeyInfoL(KIdentity1Id, KPluginBId)) + TESTL(r == KErrAuthServTrainingNotFound); + + // get key info for unregistered identity but trained plugin + TRAP(r, db->KeyInfoL(KIdentity3Id, KPluginAId)) + TESTL(r == KErrAuthServTrainingNotFound); + + // get key info for unregistered identity and untrained plugin + TRAP(r, db->KeyInfoL(KIdentity3Id, KPluginBId)); + TESTL(r == KErrAuthServTrainingNotFound); + + // ---- bad RemoveTrainedPluginL args ---- + + // clear key info for registered identity but untrained plugin + TRAP(r, db->KeyInfoL(KIdentity1Id, KPluginBId)) + TESTL(r == KErrAuthServTrainingNotFound); + + // clear key info for unregistered identity but trained plugin + TRAP(r, db->RemoveTrainedPluginL(KIdentity3Id, KPluginAId)) + TESTL(r == KErrAuthServTrainingNotFound); + + // clear key info for unregistered identity and untrained plugin + TRAP(r, db->RemoveTrainedPluginL(KIdentity3Id, KPluginBId)); + TESTL(r == KErrAuthServTrainingNotFound); + + // ----- + + // clear a present trained plugin + db->RemoveTrainedPluginL(KIdentity1Id, KPluginAId); + TRAP(r, db->KeyInfoL(KIdentity3Id, KPluginAId)) + TESTL(r == KErrAuthServTrainingNotFound); + + // register multiple trained plugins for a single identity + db->SetTrainedPluginL(KIdentity1Id, KPluginAId, tkiA); + db->SetTrainedPluginL(KIdentity1Id, KPluginBId, tkiB); + TestKeyPresentL(db, KIdentity1Id, KPluginAId, tkiA); + TestKeyPresentL(db, KIdentity1Id, KPluginAId, tkiB); + + // train a single plugin for multiple identities + db->AddIdentityL(KIdentity2Id, KIdentity2Desc); + db->SetTrainedPluginL(KIdentity2Id, KPluginAId, tkiC); + TestKeyPresentL(db, KIdentity1Id, KPluginAId, tkiA); + TestKeyPresentL(db, KIdentity1Id, KPluginBId, tkiB); + TestKeyPresentL(db, KIdentity2Id, KPluginAId, tkiC); + + // ---- atomic identity and key addition ---- + + // add identity with trained plugin + db->AddIdentityWithTrainedPluginL(KIdentity3Id, KIdentity3Desc, tkiA); + TestKeyPresentL(db, KIdentity3Id, tkiA.PluginId(), tkiA); + + // fail to add identity with trained plugin - id already exists + TRAP(r, db->AddIdentityWithTrainedPluginL(KIdentity3Id, KIdentity3Desc, tkiA)); + TESTL(r == KErrAuthServIdentityAlreadyExists); + + CleanupStack::PopAndDestroy(db); + + __UHEAP_MARKEND; + } + + +void CTStepPersist2::TestKeyPresentL( + CAuthDb2* aAuthDb, TIdentityId aIdentityId, TPluginId aPluginId, + const CTransientKeyInfo& aTarget) +/** + Helper function for TestTrainedPluginsL. + + Test the described transient key exists in the database, + and that is is equal to the supplied key. Leaves if not + the case. + + @param aAuthDb Authorisation database to retrieve + transient key info from. + @param aIdentityId Identity which should be trained for + the supplied plugin. + @param aPluginId Plugin for which the supplied identity + should be trained. + @param aTarget The retrieved transient key info should + be equal to this. + */ + { + CTransientKeyInfo* tkiActual = aAuthDb->KeyInfoL(aIdentityId, aPluginId); + CleanupStack::PushL(tkiActual); + + // ensure key infos have same externalized size + TSizeStream ssTarget; + RWriteStream wsTarget(&ssTarget); + aTarget.ExternalizeL(wsTarget); + TInt targetSize = ssTarget.Size(); + + TSizeStream ssActual; + RWriteStream wsActual(&ssActual); + tkiActual->ExternalizeL(wsActual); + TESTL(targetSize == ssActual.Size()); + + HBufC8* targetBuf = HBufC8::NewLC(targetSize); + TPtr8 targetBufDes = targetBuf->Des(); + RDesWriteStream dwsTarget(targetBufDes); + aTarget.ExternalizeL(dwsTarget); + + HBufC8* actualBuf = HBufC8::NewLC(targetSize); + TPtr8 actualBufDes = actualBuf->Des(); + RDesWriteStream dwsActual(actualBufDes); + tkiActual->ExternalizeL(dwsActual); + + TESTL(targetBufDes == actualBufDes); + + CleanupStack::PopAndDestroy(3, tkiActual); + } + + +void CTStepPersist2::TestTrainingStatusL() +/** + Test the plugins' training statuses accurately + reflect the identities which are registered + with them. + */ + { + __UHEAP_MARK; + + RemoveExistingDbL(); + + CAuthDb2* db = CAuthDb2::NewLC(iFs); + + // if there are no users then a plugin should be marked + // as untrained, even though its training count is equal + // to the number of registered identities. + TESTL(db->PluginStatusL(KPluginAId) == EAuthUntrained); + + // untrained when no users trained + db->AddIdentityL(KIdentity1Id, KIdentity1Desc); + TESTL(db->PluginStatusL(KPluginAId) == EAuthUntrained); + db->AddIdentityL(KIdentity2Id, KIdentity2Desc); + TESTL(db->PluginStatusL(KPluginAId) == EAuthUntrained); + + // trained when some, but not all, users trained + const CTransientKeyInfo& tkiA = *iId1Keys[0]; + db->SetTrainedPluginL(KIdentity1Id, KPluginAId, tkiA); + TESTL(db->PluginStatusL(KPluginAId) == EAuthTrained); + + // fully trained when all users trained + db->SetTrainedPluginL(KIdentity2Id, KPluginAId, tkiA); + TESTL(db->PluginStatusL(KPluginAId) == EAuthFullyTrained); + + // back to trained when identity untrained + db->RemoveTrainedPluginL(KIdentity1Id, KPluginAId); + TESTL(db->PluginStatusL(KPluginAId) == EAuthTrained); + + // back to untrained when last training removed + db->RemoveTrainedPluginL(KIdentity2Id, KPluginAId); + TESTL(db->PluginStatusL(KPluginAId) == EAuthUntrained); + + // restored to trained when identity trained + db->SetTrainedPluginL(KIdentity1Id, KPluginAId, tkiA); + TESTL(db->PluginStatusL(KPluginAId) == EAuthTrained); + + // restored to fully trained when last identity trained + db->SetTrainedPluginL(KIdentity2Id, KPluginAId, tkiA); + TESTL(db->PluginStatusL(KPluginAId) == EAuthFullyTrained); + + // back to trained when new identity added + db->AddIdentityL(KIdentity3Id, KIdentity3Desc); + TESTL(db->PluginStatusL(KPluginAId) == EAuthTrained); + + // upgraded to fully trained when untrained identity removed + db->RemoveIdentityL(KIdentity3Id); + TESTL(db->PluginStatusL(KPluginAId) == EAuthFullyTrained); + + // kept at fully trained when trained identity removed + db->RemoveIdentityL(KIdentity2Id); + TESTL(db->PluginStatusL(KPluginAId) == EAuthFullyTrained); + + // drop to untrained when last identity removed + db->RemoveIdentityL(KIdentity1Id); + TESTL(db->PluginStatusL(KPluginAId) == EAuthUntrained); + + CleanupStack::PopAndDestroy(db); + + __UHEAP_MARKEND; + } + + +static void IdToTestDesc(TIdentityId aId, TDes& aDesc) +/** + Helper function for TestRepairL generates a description + from the supplied identity. + + @param aId Identity Id. + @param aDesc Out paramater is populated with + description text. + */ + { + _LIT(KDescFmt, "desc_%08x"); + aDesc.Format(KDescFmt, aId); + } + + +void CTStepPersist2::TestRepairL() +/** + Test CAuthDb repairs the database if possible. + */ + { + RemoveExistingDbL(); + + CAuthDb2* db = CAuthDb2::NewLC(iFs); + + // create a set of identities + const TInt KTestIdCount = 8; + for (TInt i = 1; i <= KTestIdCount; ++i) + { + TBuf<13> buf; + IdToTestDesc(i, buf); + db->AddIdentityL(i, buf); + } + CleanupStack::PopAndDestroy(db); + + // damage the database by inserting a new entry but then + // rolling it back. + RDbNamedDatabase ndb; + TFileName dbName(KDbName); + dbName[0] = RFs::GetSystemDriveChar(); + + User::LeaveIfError(ndb.Open(iFs, dbName)); + CleanupClosePushL(ndb); + + User::LeaveIfError(ndb.Begin()); + + RDbTable table; + CleanupClosePushL(table); + User::LeaveIfError(table.Open(ndb, KIdentitiesTableName)); + + table.InsertL(); + table.SetColL(KIdentitiesIdentityIdCol, KTestIdCount+1); + table.SetColL(KIdentitiesDescCol, _L("descb")); + table.PutL(); + table.Close(); + ndb.Rollback(); + TESTL(ndb.IsDamaged()); + + CleanupStack::PopAndDestroy(2, &ndb); // table ndb + + // ensure db contains the same identities when it + // is reopened. + db = CAuthDb2::NewLC(iFs); + + RArray ids; + db->IdentitiesL(ids); + TInt idCount = ids.Count(); + ids.Reset(); + TESTL(idCount == KTestIdCount); + + for (TInt index = 1; index <= KTestIdCount; ++index) + { + TBuf<13> bufExp; + IdToTestDesc(index, bufExp); + TBuf actDesc; + HBufC* descAct = db->DescriptionL(index); + CleanupStack::PushL(descAct); + TESTL(bufExp == *descAct); + CleanupStack::PopAndDestroy(descAct); + } + CleanupStack::PopAndDestroy(db); + } + + +void CTStepPersist2::TestCompressL() +/** + Creates and deletes identities to create unused + space in database file, and tests compressed. + */ + { + RemoveExistingDbL(); + CAuthDb2* db = CAuthDb2::NewLC(iFs); + + const TInt KIdentityCount = 32; + for (TInt i = 0; i < KIdentityCount; ++i) + { + _LIT(KCompDesc, "tc-test"); + db->AddIdentityL(i, KCompDesc); + db->RemoveIdentityL(i); + } + CleanupStack::PopAndDestroy(db); + + TInt szPreComp = DbFileSizeL(); + + db = CAuthDb2::NewLC(iFs); + db->CompactIfRequired(); + CleanupStack::PopAndDestroy(db); + + TInt szPostComp = DbFileSizeL(); + + TESTL(szPreComp > szPostComp); + } + + +TInt CTStepPersist2::DbFileSizeL() +/** + Helper function for TestCompressL returns + the size of the database file in bytes. + */ + { + RFile f; + TFileName dbName(KDbName); + dbName[0] = RFs::GetSystemDriveChar(); + + User::LeaveIfError(f.Open(iFs, dbName, EFileRead | EFileStream)); + CleanupClosePushL(f); + + TInt sz; + User::LeaveIfError(f.Size(sz)); + CleanupStack::PopAndDestroy(&f); + + return sz; + } + + +