--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/authenticationservices/authenticationserver/test/tauthdb/step_persist2.cpp Tue Aug 31 17:00:08 2010 +0300
@@ -0,0 +1,595 @@
+/*
+* Copyright (c) 2005-2010 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 <s32mem.h>
+#include "tauthdbstep.h"
+#include <f32file.h>
+
+using namespace AuthServer;
+
+const TIdentityId KIdentity1Id = 0xE0494409;
+const TIdentityId KIdentity2Id = 0xE0494410;
+const TIdentityId KIdentity3Id = 0xE0494411;
+_LIT(KIdentity1Desc, "identity-1-desc");
+_LIT(KIdentity1DescB, "identity-1-descB");
+_LIT(KIdentity2Desc, "identity-2-desc");
+_LIT(KIdentity3Desc, "identity-3-desc");
+
+const TPluginId KPlugin1Id = 0xE0494433;
+const TPluginId KPlugin2Id = 0xE0494434;
+const TPluginId KPlugin3Id = 0xE0494435;
+const TPluginId KPlugin4Id = 0xE0494436;
+const TPluginId KPluginAId = 0xE0494437;
+const TPluginId KPluginBId = 0xE0494438;
+
+
+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<TIdentityId> ids;
+
+ // get id list before any ids defined
+ ids.AppendL(0xE0494499); // 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<KMaxDescLen + 1> 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<TIdentityId> 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<KMaxDescLen> 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;
+ }
+
+
+