symhelp/helpmodel/tsrc/TSearch.cpp
changeset 0 1f04cf54edd8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/symhelp/helpmodel/tsrc/TSearch.cpp	Tue Jan 26 15:15:23 2010 +0200
@@ -0,0 +1,717 @@
+// Copyright (c) 1999-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:
+// Test Help Model module to check the PlatSec search order.
+// This test uses and additional drive typically F: It should be mapped in the epoc.ini file.
+// Mapping is achieved for example thus: _EPOC_DRIVE_F c:\temp
+// 
+//
+
+// System includes
+#include <e32std.h>
+#include <e32def.h>
+
+
+#include <e32test.h>
+#include <e32math.h>
+#include <f32file.h>
+#include <coehelp.h>
+
+// User includes
+#include <bautils.h>
+#include "HLPMODEL.H"
+#include <coreappstest/testserver.h>
+#include "SearchOrderTest.h"
+
+// Globals
+static TInt64				TheSeed;
+static RFs					TheFs;
+static RTest				TheTest(_L("TSearch - Test Help Model Searching"));
+static CTrapCleanup*		TheTrapCleanup;
+static CActiveScheduler*	TheScheduler;
+
+// Constants
+const TInt KTestCleanupStack=0x20;
+
+
+// Panic enum
+enum THlpPanic
+	{
+	EHlpPanicNoBossFile,
+	EHlpPanicLast
+	};
+
+
+//
+// ---------> Global functions
+//
+
+static void Panic(THlpPanic aPanic)
+	{
+	_LIT(KHlpPanicCategory, "TSearch");
+	User::Panic(KHlpPanicCategory, aPanic);
+	}
+
+
+static TInt Rand(const TInt aLow, const TInt aHigh)
+//
+//	Generate a random number based upon a seed and a range
+//
+	{
+	TReal initialRand = (Math::FRand(TheSeed) * (aHigh - aLow));
+	TInt32 rand;
+
+	// Round to 0 decimal places, ie. the nearest whole numer
+	Math::Round(initialRand, initialRand, 0);
+	Math::Int(rand, initialRand);
+
+	//aSeed = seed;
+	return (aLow + rand);
+	}
+
+
+
+//
+// ---------> CHlpSearchTest (header)
+//
+class CHlpSearchTest: public CBase, public MHlpModelObserver
+	{
+public: // CONSTRUCT / DESTRUCT
+	static void TestHelpModelLD(TBool aOomTesting = EFalse);
+	~CHlpSearchTest();
+
+private:
+	CHlpSearchTest();	
+
+public: // NEW
+	void TestL(TBool aOomTesting = EFalse);
+
+public: // FROM MHlpModelObserver
+	void HandleModelEventL(TInt aEvent);
+
+private: // TESTING METHODS
+	void BasicCreateAndCloseL();
+	void IndexListL(TBool aOomTesting = EFalse);
+	void CategoryListL(TBool aOomTesting = EFalse);
+	void TopicListForCategoryL();
+	void ContextSearchL(TBool aOomTesting = EFalse);
+	void IndexSearchL();
+	void TextSearchL(TBool aOomTesting = EFalse);
+	void CategoryUidSearchL(TBool aOomTesting = EFalse);
+
+private:
+	void Reset();
+	TBool FileExists(const TDesC& aFileName);
+	CDesCArray* CategoryListLC();
+	
+private: // MEMBER DATA
+	TInt iResponseCount;
+	TInt iLastHelpModelResponse;
+	TInt iSearchProgressCount;
+	TInt iSearchCancelValue;
+	TBool iIsAsynchronous;
+	TBool iSchedulerStarted;
+	CHlpModel* iModel;
+	};
+
+
+
+
+
+
+//
+// ---------> CHlpSearchTest (source)
+//
+
+CHlpSearchTest::CHlpSearchTest()
+	{
+	}
+
+
+CHlpSearchTest::~CHlpSearchTest()
+	{
+	delete iModel;
+	}
+
+
+void CHlpSearchTest::TestHelpModelLD(TBool aOomTesting)
+	{
+	CHlpSearchTest* self = new(ELeave) CHlpSearchTest();
+	CleanupStack::PushL(self);
+	self->TestL(aOomTesting);
+	CleanupStack::PopAndDestroy();
+	}
+
+
+//
+//
+//
+
+
+void CHlpSearchTest::TestL(TBool aOomTesting)
+	{
+	iModel = CHlpModel::NewL(TheFs, this);
+	iModel->OpenL();
+
+
+	BasicCreateAndCloseL();
+	IndexListL(aOomTesting);
+	CategoryListL(aOomTesting);
+	TopicListForCategoryL();
+	ContextSearchL(aOomTesting);
+	TextSearchL(aOomTesting);
+	CategoryUidSearchL(aOomTesting);
+	}
+
+
+//
+//
+//
+
+void CHlpSearchTest::BasicCreateAndCloseL()
+	{
+	TheTest.Console()->ClearScreen();
+	TheTest.Printf(_L("Testing basic open, close and destruction\n"));
+
+	__UHEAP_MARK;
+	CHlpModel::NewLC(TheFs, NULL);
+	CleanupStack::PopAndDestroy(); // model
+	__UHEAP_MARKEND;
+
+	__UHEAP_MARK;
+	CHlpModel* model = CHlpModel::NewLC(TheFs, NULL);
+	model->OpenL();
+	CleanupStack::PopAndDestroy(); // model
+	__UHEAP_MARKEND;
+	}
+
+void CHlpSearchTest::IndexListL(TBool aOomTesting)
+	{
+	TheTest.Console()->ClearScreen();
+	TheTest.Printf(_L("Testing index listing\n"));
+	Reset();
+	
+	iModel->SearchL(EIndexList);
+
+	if(!aOomTesting)
+		{
+		TheTest(iLastHelpModelResponse == EIndexListAvailable);
+		}
+	TheTest(iResponseCount == 1);
+
+	// Load the complete list of entries for all help files
+	CHlpList* list = CHlpList::NewLC();
+	iModel->LoadListL(list);
+	TheTest.Printf(_L("\tComplete index listing for all help files..."));
+	TInt i=0;
+	for(i=0; i<list->MdcaCount(); i++)
+		{
+		CHlpItem* item = list->Item(i);
+		TPtrC pItem(item->Title());
+		TheTest.Printf(_L("\nIndex list [0x%08x][indexId=%d]: %S "), item->HelpFileUid(), item->Id(), &pItem);
+		}
+	TheTest.Printf(_L("\n"));
+
+	// Next select an item from the complete list (at random)
+
+	if(list->MdcaCount()!=0)
+		{
+		CHlpItem* item = list->Item(Rand(0, list->MdcaCount()-1));
+		
+		// Save these for later...
+		TUint helpFileUid = item->HelpFileUid().iUid;
+		TUint indexId = item->Id();
+
+		// Next perform a topic search based on this item
+		iModel->IndexSearchL(*item);
+		TheTest(iLastHelpModelResponse == EIndexSearchListAvailable);
+		CleanupStack::PopAndDestroy(); // list
+
+		// Next load the list of topics which match the index id
+		list = CHlpList::NewLC();
+		iModel->LoadListL(list);
+		TheTest.Printf(_L("\tTopic listing in help file 0x%08x, whose index id = %d"), helpFileUid, indexId);
+		for(i=0; i<list->MdcaCount(); i++)
+			{
+			CHlpItem* item = list->Item(i);
+			TPtrC pItem(item->Title());
+			TheTest.Printf(_L("\nTopic [Uid: 0x%08x]: %S "), item->HelpFileUid(), &pItem);
+			}
+	}
+	TheTest.Printf(_L("\n"));
+
+	CleanupStack::PopAndDestroy(); // list
+	}
+
+
+void CHlpSearchTest::CategoryListL(TBool aOomTesting)
+	{
+	TheTest.Console()->ClearScreen();
+	TheTest.Printf(_L("Testing category listing\n"));
+
+	Reset();
+	iModel->SearchL(ECategoryList);
+	if(!aOomTesting)
+		{
+		TheTest(iLastHelpModelResponse == ECategoryListAvailable);
+		}
+
+	// Display the index listing...
+	CHlpList* list = CHlpList::NewLC();
+	iModel->LoadListL(list);
+
+	for(TInt i=0; i<list->MdcaCount(); i++)
+		{
+		TPtrC pItem(list->MdcaPoint(i));
+		TheTest.Printf(_L("\nCategory item %d: %S"), i, &pItem);
+		}
+	TheTest.Printf(_L("\n"));
+	CleanupStack::PopAndDestroy(); // list
+	}
+
+
+void CHlpSearchTest::TopicListForCategoryL()
+	{
+	TheTest.Printf(_L("Testing topic listing\n"));
+	Reset();
+
+	// First get a category listing, then get the list of topics
+	// for each specified category.
+	CDesCArrayFlat* array = STATIC_CAST(CDesCArrayFlat*, CategoryListLC());
+	const TInt count = array->Count();
+	for(TInt i=0; i<count; i++)
+		{
+		TPtrC pItem = array->MdcaPoint(i);
+		TheTest.Printf(_L("\nTopics for Category %S\n"), &pItem);
+
+		// Calling this will result in the topics for this category
+		// being printed out in the mixin handler
+		iModel->SearchL(ETopicListForCategory, pItem);
+		}
+	CleanupStack::PopAndDestroy(); // array
+	}
+
+
+void CHlpSearchTest::ContextSearchL(TBool aOomTesting)
+	{
+	TheTest.Printf(_L("Testing context searching\n"));
+	Reset();
+
+	// Context search for an item we know exists
+	_LIT(KContext1,	"This_is_a_multi_word_context2");
+
+	TUid uid = { 16777216 };
+	TCoeHelpContext coeSearchContext(uid, KContext1);
+	iModel->ContextSearchL(coeSearchContext);
+	if(!aOomTesting)
+		{
+		TheTest(iLastHelpModelResponse == ETopicAvailable);
+		}
+
+	
+	// Context search for an item we know doesn't exist
+	_LIT(KContext2,	"ABCDEFG");
+
+	TUid uid2 = { 00000000 };
+	TCoeHelpContext coeSearchContext2(uid2, KContext2);
+	iModel->ContextSearchL(coeSearchContext2);
+	TheTest(iLastHelpModelResponse == ETopicNotFound);
+	}
+
+
+void CHlpSearchTest::TextSearchL(TBool aOomTesting)
+	{
+	if(aOomTesting)
+		return;
+
+	_LIT(KFullTextShouldNotBeFound,	"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
+	TheTest.Printf(_L("Testing text searching (when item shouldn't be found)\n"));
+
+	Reset();
+	iSchedulerStarted = EFalse;
+	iIsAsynchronous = ETrue;
+	iModel->SearchL(EFullTextSearch, KFullTextShouldNotBeFound);
+	iSchedulerStarted = ETrue;
+	CActiveScheduler::Start();
+	TheTest(iLastHelpModelResponse == ESearchListNoneFound);
+
+	_LIT(KFullTextShouldBeFound,	"boss");
+	TheTest.Printf(_L("Testing text searching (when item should be found)\n"));
+
+	Reset();
+	iSchedulerStarted = EFalse;
+	iIsAsynchronous = ETrue;
+	iModel->SearchL(EFullTextSearch, KFullTextShouldBeFound);
+	iSchedulerStarted = ETrue;
+	CActiveScheduler::Start();
+	TheTest(iLastHelpModelResponse == ESearchListAvailable);
+
+	TheTest.Printf(_L("\tTesting asynch cancel function\n"));
+	TInt searchCancelValue = Max(1, iSearchProgressCount / 2); // stop half way through
+
+	Reset();
+	iSearchCancelValue = searchCancelValue;
+	iSchedulerStarted = EFalse;
+	iIsAsynchronous = ETrue;
+	iModel->SearchL(EFullTextSearch, KFullTextShouldBeFound);
+	iSchedulerStarted = ETrue;
+	CActiveScheduler::Start();
+	}
+
+
+void CHlpSearchTest::CategoryUidSearchL(TBool aOomTesting)
+	{
+	TheTest.Console()->ClearScreen();
+	TheTest.Printf(_L("Testing category uid searching - *requires boss help file*\n"));
+	
+
+    if	((!FileExists(_L("C:\\Resource\\Help\\Boss-1.hlp"))) && (!FileExists(_L("Z:\\Resource\\Help\\Boss-1.hlp"))))
+		Panic(EHlpPanicNoBossFile);
+	
+
+	Reset();
+	iModel->CategoryUIDSearchL(TUid::Uid(16777216)); // hard coded category uid from Boss1.hlp
+	if(!aOomTesting)
+		{
+		TheTest(iLastHelpModelResponse == ETopicListAvailable);
+		}
+	TheTest(iResponseCount == 1);
+
+	// Display the index listing...
+	CHlpList* list = CHlpList::NewLC();
+	iModel->LoadListL(list);
+
+	for(TInt i=0; i<list->MdcaCount(); i++)
+		{
+		TPtrC pItem(list->MdcaPoint(i));
+		TheTest.Printf(_L("\nCategory item %d: %S"), i, &pItem);
+		}
+	CleanupStack::PopAndDestroy(); // list
+	TheTest.Printf(_L("\n"));
+
+	// Test for a category that we know doesn't exist
+	Reset();
+	iModel->CategoryUIDSearchL(KNullUid);
+	TheTest(iLastHelpModelResponse == ETopicListNoneFound);
+	TheTest(iResponseCount == 1);
+	}
+
+
+//
+//
+//
+
+
+void CHlpSearchTest::Reset()
+	{
+	iResponseCount = 0;
+	iLastHelpModelResponse = KErrGeneral;
+	iIsAsynchronous = EFalse;
+	iSearchProgressCount = 0;
+	iSearchCancelValue = KErrNone-1; // Anything less that KErrNone
+	}
+
+TBool CHlpSearchTest::FileExists(const TDesC& aFileName)
+	{
+	TEntry entry;
+	TInt error = TheFs.Entry(aFileName, entry);
+	if	(error == KErrInUse)
+		return ETrue;
+	if	(error < KErrNone)
+		return EFalse;
+	return (!entry.IsDir());
+	}
+
+CDesCArray* CHlpSearchTest::CategoryListLC()
+	{
+	// Get and print the category listing
+	CDesCArrayFlat* array = new(ELeave) CDesCArrayFlat(5);
+	CleanupStack::PushL(array);
+	iModel->CategoryListL(array);
+	return array;
+	}
+
+
+//
+//
+//
+
+
+void CHlpSearchTest::HandleModelEventL(TInt aEvent)
+	{
+	iResponseCount++;
+	iLastHelpModelResponse = aEvent;
+
+	// If this test included an asynch search, and there was a cancel value set
+	// then cancel the asynch searcher
+	if	(++iSearchProgressCount == iSearchCancelValue && iIsAsynchronous)
+		{
+		// Reset this otherwise we'll get stuck in a loop
+		iSearchCancelValue = KErrNone-1;
+
+		// Only works for full test searching as this is the only search type 
+		// which uses an active object, and even then it doesn't use them properly.
+		TheTest(iModel->CancelSearch() == KErrNone);
+		}
+
+	switch (aEvent)
+		{
+	case ESearchListAvailable:		// text searches
+		TheTest.Printf(_L("\n\tESearchListAvailable\n"));
+		break;
+	
+	case ECategoryListAvailable:
+		{
+		TheTest.Printf(_L("\n\tECategoryListAvailable\n"));
+
+		// Get and print the category listing
+		CDesCArrayFlat* array = STATIC_CAST(CDesCArrayFlat*, CategoryListLC());
+		const TInt count = array->Count();
+		for(TInt i=0; i<count; i++)
+			{
+			TPtrC pItem = array->MdcaPoint(i);
+			TheTest.Printf(_L("Category %d: %S\n"), i, &pItem);
+			}
+		CleanupStack::PopAndDestroy(); // array
+		break;
+		}
+	case ECategoryListNoneFound:
+		TheTest.Printf(_L("\n\tECategoryListNoneFound\n"));
+		break;
+
+
+	case ETopicListAvailable:		// category expansion
+		{
+		TheTest.Printf(_L("\n\tETopicListAvailable\n"));
+		CHlpList* list = CHlpList::NewLC();
+		iModel->LoadListL(list);
+		TInt count = list->MdcaCount();
+		for(TInt i=0; i<count; i++)
+			{
+			CHlpItem* item = list->Item(i);
+			TPtrC pTitle(*item->iTitle);
+			TheTest.Printf(_L("Topic %d: %S (id = %d)\n"), i, &pTitle, item->iId);
+			}
+		CleanupStack::PopAndDestroy(); // list
+		break;
+		}
+	case ETopicListNoneFound:
+		TheTest.Printf(_L("\n\tETopicListNoneFound\n"));
+		break;
+
+	
+	case ETopicAvailable:			// topic text
+		TheTest.Printf(_L("\n\tETopicAvailable\n"));
+		break;
+	case ETopicNotFound:
+		TheTest.Printf(_L("\n\tETopicNotFound\n"));
+		break;
+
+
+	case EIndexListAvailable:		// index list
+		TheTest.Printf(_L("\n\tEIndexListAvailable\n"));
+		break;
+	case EIndexListNoneFound:
+		TheTest.Printf(_L("\n\tEIndexListNoneFound\n"));
+		break;
+	case EIndexSearchListAvailable:	// topic list from index phrase
+		TheTest.Printf(_L("\n\tEIndexSearchListAvailable\n"));
+		break;
+	case EIndexSearchListNoneFound:
+		TheTest.Printf(_L("\n\tEIndexSearchListNoneFound\n"));
+		break;
+
+
+	case EHlpSearchCancelled:
+		TheTest.Printf(_L("<SEARCH CANCELLED>"));
+		break;
+	case EModelSearchInProgress:
+		TheTest.Printf(_L("..."));
+		return;
+	case ESearchListNoneFound:
+		TheTest.Printf(_L("\n\tESearchListNoneFound\n"));
+		break;
+		}
+
+	if	(iIsAsynchronous && iSchedulerStarted)
+		CActiveScheduler::Stop();
+	}
+	
+/**
+	doSearchOrderTest
+	
+	All help files used in this part of the test use the Category UID of 0x01007000
+	Within each source RTF file the Category is defined as the drive name.
+	Hence the File copied to c:\resource\help has the Category "Drive C:"
+	There are 3 help files used in this test:
+		PlatSecSearchTestC.hlp - initially resides in z:\System\Programs\THlpmodel\
+		PlatSecSearchTestF.hlp - initially resides in z:\System\Programs\THlpmodel\
+		PlatSecSearchTest.hlp - (with Category "Drive Z:") resides in z:\Resoruce\Help
+	The exports are specified in the Hlpmodel BLD.INF file.
+	
+	As part of the building process the help files are exported to the
+	corresponding directories.
+
+	Thus initially only PlatSecSearchTest.hlp with be visible presenting 
+	the Category "Drive Z:". As the test progresses so the 2 remaining files are
+	copied (with a change in name) from z:\System\Programs\THlpmodel\ to their corresponding drive.
+	Thus PlatSecSearchTestC.hlp becomes PlatSecSearchTest.hlp in c:\Resource\Help
+	and PlatSecSearchTestF.hlp becomes PlatSecSearchTest.hlp in f:\Resource\Help
+	
+	Given the search order, the higher drive letter takes presidence (however z: is last),
+	so when there are is a file called PlatSecSearchTest.hlp on z:, c: and f: only f: 
+	will be seen.
+	
+	Note: That the test looks for a drive of type EMediaHardDisk: on Lubbock this will be F:
+	on the H2 it is likely to be E: this is managed within CSearchOrderTest.
+*/
+
+
+
+static void doSearchOrderTestL()
+	{
+	__UHEAP_MARK;
+	TheTest.Printf(_L("-------------------------------------------\n"));				
+	TheTest.Printf(_L("   Testing PlatSec drive search Order.\n"));			
+	TheTest.Printf(_L("-------------------------------------------\n"));				
+
+	// Initialise the array of mapped drives.
+	CSearchOrderTest* sort = CSearchOrderTest::NewL(TheTest);
+	CleanupStack::PushL( sort );
+	
+	TheTest.Next(_L("Test category listing"));
+	
+	CHlpModel* model = CHlpModel::NewLC(TheFs, NULL);
+
+	CDesCArray* catList = new(ELeave) CDesCArrayFlat(2);
+	CleanupStack::PushL(catList);
+		
+	// Iterate around Drive Loop
+	TBool found = EFalse;
+	for( TInt operation =CSearchOrderTest::EInitial_DeleteAll;
+		 operation<=CSearchOrderTest::EFinal_DeleteAll; 
+		 operation++)
+		{
+		sort->MoveHelpFileL( operation );
+		model->OpenL();
+		// Get the new gategory list, resulting from the repositioned file.
+		model->CategoryListL(catList);
+		// Close help model to release file handles.
+		model->CloseL();
+		// Check listed categories given the current index.
+		found = sort->CheckCategoryListL( operation, catList );
+		if( found )
+			{
+			TheTest.Printf(_L("The Correct Category was found."));			
+			}
+		TheTest(found);
+		// Remove the old contents, otherwise new 
+		// categories are simply added.
+		catList->Reset();
+		}
+	CleanupStack::PopAndDestroy( catList );
+	CleanupStack::PopAndDestroy( model );
+	CleanupStack::PopAndDestroy( sort );
+	__UHEAP_MARKEND;
+	}
+
+static void PerformOOMTestL()
+	{
+	TInt ret=KErrNoMemory;
+	TInt failAt=0;	  
+	while (ret!=KErrNone)
+		{
+		failAt++;
+		__UHEAP_SETFAIL(RHeap::EDeterministic,failAt);
+		__UHEAP_MARK;			
+		TRAP(ret, CHlpSearchTest::TestHelpModelLD(ETrue));
+		if (ret!=KErrNone)
+			{
+			__UHEAP_MARKEND;
+			}
+		__UHEAP_RESET;
+		TheTest(ret==KErrNoMemory||ret==KErrNone);
+		}
+	}
+
+static void setupFileServerAndSchedulerL()
+//
+// Initialise the cleanup stack.
+//
+	{
+	TTime time;
+	time.HomeTime();
+	TheSeed = time.Int64();
+
+	TheTest(TheFs.Connect() == KErrNone);
+	TheScheduler = new (ELeave) CActiveScheduler;
+	CActiveScheduler::Install(TheScheduler);
+	}
+
+
+static void setupCleanup()
+//
+// Initialise the cleanup stack.
+//
+    {
+	TheTrapCleanup = CTrapCleanup::New();
+	TheTest(TheTrapCleanup!=NULL);
+	TRAPD(r,
+		{
+		for (TInt i=KTestCleanupStack;i>0;i--)
+			CleanupStack::PushL((TAny*) 0);
+		CleanupStack::Pop(KTestCleanupStack);
+		});
+	TheTest(r==KErrNone);
+	}
+
+/**
+@SYMTestCaseID PIM-TSEARCH-0001
+*/	
+GLDEF_C TInt E32Main()
+//
+// Test Help Model API
+//
+    {
+	__UHEAP_MARK;
+
+	TheTest.Title();
+	TheTest.Start(_L("@SYMTestCaseID PIM-TSEARCH-0001"));
+	setupCleanup();
+	
+	__UHEAP_MARK;
+	TRAPD(r, 
+			setupFileServerAndSchedulerL();
+			CHlpSearchTest::TestHelpModelLD();
+			);
+	
+	TheTest(r==KErrNone);
+	__UHEAP_MARKEND;
+	
+	TRAP(r, PerformOOMTestL());
+	TheTest(r==KErrNone);
+	
+	// PlatSec search order test.
+	TRAP(r, doSearchOrderTestL());
+	TheTest(r==KErrNone);
+
+
+	delete TheScheduler;
+	delete TheTrapCleanup;
+	TheFs.Close();
+	TheTest.End();
+	TheTest.Close();
+
+	__UHEAP_MARKEND;
+	return KErrNone;
+    }