diff -r 000000000000 -r bde4ae8d615e os/persistentdata/persistentstorage/store/TPAGE/t_storpage.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/os/persistentdata/persistentstorage/store/TPAGE/t_storpage.cpp	Fri Jun 15 03:10:57 2012 +0200
@@ -0,0 +1,671 @@
+// Copyright (c) 1998-2010 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:
+//
+
+#include <s32cont.h>
+#include <s32file.h>
+#include <s32crypt.h>
+#include <e32test.h>
+#include <pbe.h>
+#include "UP_STD.H"
+
+const TInt KTestCleanupStack=0x20;
+
+// This is a path specification and should not be used as is
+_LIT(KFileLocationSpec, "Z:\\STOR-TST\\T_SPAGE.DAT");
+_LIT(KPageFilePath, "C:\\TestSTOR\\T_SPAGEFILE.PAG");
+_LIT(KPageFilePathOnly, "C:\\TestSTOR\\");
+
+LOCAL_D CTrapCleanup* TheTrapCleanup;
+LOCAL_D RTest TheTest(_L("t_storpage"));
+LOCAL_D RFs TheFs;
+LOCAL_D CFileStore* TheStore;
+
+///////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////
+//Tests macros and functions.
+//If (!aValue) then the test will be panicked, the test data files will be deleted.
+static void Check(TInt aValue, TInt aLine)
+	{
+	if(!aValue)
+		{
+		TheTest.Printf(_L("*** Boolean expression evaluated to false!\r\n"));
+		TheTest(EFalse, aLine);
+		}
+	}
+//If (aValue != aExpected) then the test will be panicked, the test data files will be deleted.
+static void Check(TInt aValue, TInt aExpected, TInt aLine)
+	{
+	if(aValue != aExpected)
+		{
+		TheTest.Printf(_L("*** Expected error: %d, got: %d\r\n"), aExpected, aValue);
+		TheTest(EFalse, aLine);
+		}
+	}
+//Use these to test conditions.
+#define TEST(arg) ::Check((arg), __LINE__)
+#define TEST2(aValue, aExpected) ::Check(aValue, aExpected, __LINE__)
+
+///////////////////////////////////////////////////////////////////////////////////////
+
+/**
+@SYMTestCaseID          SYSLIB-STORE-CT-1178
+@SYMTestCaseDesc	    TPagedSet functionality test
+@SYMTestPriority 	    High
+@SYMTestActions  	    Tests for insert,delete,contains,with and without duplicates operations
+@SYMTestExpectedResults Test must not fail
+@SYMREQ                 REQ0000
+*/
+LOCAL_C void test1L(MPagePool& aPagePool)
+	{
+	const TInt KEntryCount=200;
+
+	TPagedSet<TInt32> set;
+	set.Connect(&aPagePool);
+	TheTest.Start(_L(" @SYMTestCaseID:SYSLIB-STORE-CT-1178 Insertion & Deletion "));
+
+	TInt32 it=0;
+	set.InsertL(it);
+	TEST2(set.Count(), 1);
+	TRAPD(r,set.InsertL(it));
+	TEST2(r, KErrAlreadyExists);
+	TEST2(set.Count(), 1);
+	TEST(set.ContainsL(it));
+	set.DeleteL(it);
+	TEST2(set.Count(), 0);
+	TRAP(r,set.DeleteL(it));
+	TEST2(r, KErrNotFound);
+	TEST2(set.Count(), 0);
+	TEST(!set.ContainsL(it));
+
+	TheTest.Next(_L("No duplicates"));
+	TInt ii;
+	for (ii=0;ii<KEntryCount;++ii)
+		{
+		it=ii;
+		set.InsertL(it);
+		}
+	for (ii=0;ii<KEntryCount;++ii)
+		{
+		it=ii;
+		TEST(set.ContainsL(it));
+		}
+	TEST2(set.Count(), KEntryCount);
+
+	TheTest.Next(_L("Empty the set"));
+	set.ClearL();
+	TEST2(set.Count(), 0);
+	for (ii=0;ii<KEntryCount;++ii)
+		{
+		it=ii;
+		TEST(!set.ContainsL(it));
+		}
+
+	TheTest.End();
+	}
+
+struct TTest
+	{
+	inline TTest() {Mem::FillZ(this,sizeof(*this));}
+	TUint32 iVal;
+	TUint32 iPadding[14];
+	};
+
+/**
+@SYMTestCaseID          SYSLIB-STORE-CT-1179
+@SYMTestCaseDesc	    Tests for large set of TUint32
+@SYMTestPriority 	    High
+@SYMTestActions  	    Tests for inserting,contains,iteration,deletion operations
+@SYMTestExpectedResults Test must not fail
+@SYMREQ                 REQ0000
+*/
+LOCAL_C void test2L(MPagePool& aPagePool)
+	{
+	const TInt KEntryCount=500;
+
+	TPagedSet<TTest> set;
+	set.Connect(&aPagePool);
+	TTest item;
+
+	TheTest.Start(_L(" @SYMTestCaseID:SYSLIB-STORE-CT-1179 Add items "));
+	TUint32 jj=0;
+	TInt32 ii;
+	for (ii=KEntryCount;ii>0;--ii)
+		{
+		jj=(jj+17)%KEntryCount;
+		item.iVal=jj;
+		set.InsertL(item);
+		}
+	TEST2(set.Count(), KEntryCount);
+
+	TheTest.Next(_L("Check contents"));
+	for (ii=0;ii<KEntryCount;++ii)
+		{
+		item.iVal=ii;
+		TEST(set.ContainsL(item));
+		}
+
+	TheTest.Next(_L("Iterate over items"));
+	TUint8 *checkMap=(TUint8*)User::AllocLC(KEntryCount);
+	Mem::FillZ(checkMap,KEntryCount);
+	TPagedSetIter<TTest> iter(set);
+	if (iter.ResetL())
+		do	++checkMap[iter.AtL().iVal]; while (iter.NextL());
+	for (ii=0;ii<KEntryCount;++ii)
+		TEST2(checkMap[ii], 1);
+	CleanupStack::PopAndDestroy();
+
+	TheTest.Next(_L("Delete items"));
+	jj=0;
+	for (ii=KEntryCount;ii>KEntryCount/2;--ii)
+		{
+		jj=(jj+17)%KEntryCount;
+		item.iVal=jj;
+		set.DeleteL(item);
+		}
+	TEST2(set.Count(), KEntryCount/2);
+
+	TheTest.Next(_L("Check contents"));
+	for (;ii>0;--ii)
+		{
+		jj=(jj+17)%KEntryCount;
+		item.iVal=jj;
+		TEST(set.ContainsL(item));
+		}
+	jj=0;
+	for (ii=KEntryCount;ii>KEntryCount/2;--ii)
+		{
+		jj=(jj+17)%KEntryCount;
+		item.iVal=jj;
+		TEST(!set.ContainsL(item));
+		}
+
+	TheTest.Next(_L("Delete items"));
+	for (;ii>1;--ii)
+		{
+		jj=(jj+17)%KEntryCount;
+		item.iVal=jj;
+		set.DeleteL(item);
+		}
+	TEST2(set.Count(), 1);
+
+	TheTest.Next(_L("Check contents"));
+	jj=(jj+17)%KEntryCount;
+	TPagedSetBiIter<TTest> biter(set);
+	TEST(biter.FirstL());
+	TEST2(biter.AtL().iVal, jj);
+	TEST(!biter.NextL());
+	TEST(biter.LastL());
+	TEST2(biter.AtL().iVal ,jj);
+	TEST(!biter.PreviousL());
+	TPagedSetRIter<TTest> riter(set);
+	TEST(riter.ResetL());
+	TEST2(riter.AtL().iVal, jj);
+	TEST(!riter.NextL());
+
+	item.iVal=jj;
+	set.DeleteL(item);
+	TEST(!iter.ResetL());
+	TEST2(set.Count(), 0);
+
+	TheTest.End();
+	}
+
+/**
+@SYMTestCaseID          SYSLIB-STORE-CT-1180
+@SYMTestCaseDesc	    Streaming tests
+@SYMTestPriority 	    High
+@SYMTestActions  	    Tests for read and write operations on the streams
+@SYMTestExpectedResults Test must not fail
+@SYMREQ                 REQ0000
+*/
+LOCAL_C void test3L(RStorePagePool& aPool)
+	{
+	const TInt KEntryCount=1000;
+	TheTest.Start(_L(" @SYMTestCaseID:SYSLIB-STORE-CT-1180 Build set and stream out "));
+	aPool.Create(*TheStore);
+	TBool rc = aPool.HasAvailable();
+	TEST(!rc);
+	rc = aPool.IsEmpty();
+	TEST(rc);
+	TStorePagePoolToken token2(TStorePagePoolToken::EEmpty);
+	token2 = aPool.Token();
+	rc = token2.IsEmpty();
+	TEST(rc);
+	rc = token2.HasAvailable();
+	TEST(!rc);
+	
+	TPagedSet<TInt32> set1;
+	set1.Connect(&aPool);
+
+	TInt ii;
+	for (ii=0;ii<KEntryCount;ii++)
+		{
+		TInt32 it=ii;
+		set1.InsertL(it);
+		}
+	aPool.FlushL();
+	
+	RStoreWriteStream out;
+	TStreamId id=out.CreateLC(*TheStore);
+	out<<aPool.Token();
+	out<<set1.Token();
+	out.CommitL();
+	CleanupStack::PopAndDestroy();	// out
+	aPool.Close();
+//
+	TheTest.Next(_L("Stream in and test set"));
+	RStoreReadStream in;
+	in.OpenLC(*TheStore,id);
+	TStorePagePoolToken ptoken;
+	in>>ptoken;
+	aPool.Open(*TheStore,ptoken);
+	TEST(!aPool.IsDirty());
+	TPagedSetToken token;
+	in>>token;
+	TPagedSet<TInt32> set2(token);
+	set2.Connect(&aPool);
+	TEST(set2.IsIntact());
+	CleanupStack::PopAndDestroy();	// in
+
+	TEST2(set2.Count(), KEntryCount);
+	for (ii=0;ii<KEntryCount;ii++)
+		{
+		TInt32 it=ii;
+		set2.DeleteL(it);
+		}
+	TEST2(set2.Count(), 0);
+	aPool.FlushL();
+	aPool.Discard();
+	aPool.ReclaimAllL();
+	aPool.Close();
+	TheTest.End();
+	}
+
+/**
+@SYMTestCaseID          PDS-STORE-CT-4009
+@SYMTestCaseDesc	    RFilePagePool tests
+@SYMTestPriority 	    High
+@SYMTestActions  	    Tests for creating and opening RFilePagePool
+@SYMTestExpectedResults RFilePagePool needs to be correctly created, replaced and opened.
+@SYMDEF                 DEF135804
+*/
+LOCAL_C void test4L()
+	{
+	RFilePagePool testPage;
+	TFileName tempPageFileName;
+	RFs fs;
+	TInt err;
+	fs.Connect();
+	err = fs.MkDirAll(KPageFilePathOnly);
+	TEST(err==KErrNone||err==KErrAlreadyExists);
+	err = fs.Delete(KPageFilePath);
+	TEST(err==KErrNone||err==KErrNotFound);
+	CPageCache* pcache = CPageCache::NewLC(2);
+	//creating file
+	TheTest.Printf(_L("Creating file for the page pool"));
+	err = testPage.Create(fs, KPageFilePath, EFileWrite);
+	TEST2(err, KErrNone);
+	testPage.Set(*pcache);
+	TheTest.Printf(_L("-> File created -> Closing "));
+	testPage.Close();
+	TheTest.Printf(_L("-> Closed "));
+	//opening file, file should be present after successful creation
+	TheTest.Printf(_L("Opening file for the page pool"));
+	err = testPage.Open(fs,KPageFilePath, EFileWrite);
+	TEST2(err, KErrNone);
+	testPage.Set(*pcache);
+	TheTest.Printf(_L("-> File opened -> Closing "));
+	testPage.Close();
+	TheTest.Printf(_L("-> Closed "));
+	//try to replace already existing file
+	//file should exist after successful creation
+	TheTest.Printf(_L("Replacing file for the page pool"));
+	err = testPage.Replace(fs, KPageFilePath, EFileWrite);
+	TEST2(err, KErrNone);
+	testPage.Set(*pcache);
+	TheTest.Printf(_L("-> File replaced -> Closing "));
+	testPage.Close();
+	TheTest.Printf(_L("-> Closed "));
+	//try to create temp file with unique name
+	TheTest.Printf(_L("Creating temp unique file "));
+	err = testPage.Temp(fs, KPageFilePathOnly, tempPageFileName, EFileWrite);
+	TEST2(err, KErrNone);
+	testPage.Set(*pcache);
+	TheTest.Printf(_L("-> File created -> Closing "));
+	testPage.Close();
+	TheTest.Printf(_L("-> Closed "));
+	//if file was propertly created we should be able to open it
+	TheTest.Printf(_L("Opening temp unique file "));
+	err = testPage.Open(fs, tempPageFileName, EFileWrite);
+	TEST2(err, KErrNone);
+	TheTest.Printf(_L("-> File opened -> Releasing "));
+	testPage.Release();
+	TheTest.Printf(_L("-> Released "));
+	
+	//open and flush temp file
+	RFilePagePool testPage2(*pcache);
+	err = testPage2.Open(fs, tempPageFileName, EFileWrite);
+	TEST2(err, KErrNone);
+	err = testPage2.Flush();
+	TEST2(err, KErrNone);
+	TRAP(err, testPage2.FlushL());
+	TEST2(err, KErrNone);
+	
+	RFile& file = const_cast<RFile&>(testPage2.File());
+	TFileName testIsSameFile;
+	file.FullName(testIsSameFile);
+	TEST2( testIsSameFile.Compare(tempPageFileName), 0);
+	testPage2.Detach();
+	file.Close();
+	
+	//attach and detach file
+	file.Open(fs, testIsSameFile, EFileWrite|EFileShareReadersOrWriters);
+	testPage2.Attach(file);
+	testPage2.Detach();
+	file.Close();
+	testPage2.Close();
+	
+	CleanupStack::PopAndDestroy(pcache);
+	fs.Close();
+	}
+
+/**
+ * Struct needed in test5()
+ */
+struct SCachePage
+	{
+	TCachePage iPage[1];
+	TUint8 iData[KPoolPageSize];
+	};
+/**
+ * Class specially created to test protected API from RFilePagePool
+ */
+class RFilePagePoolTestClass: public RFilePagePool
+	{
+public:
+	void CallProtectedWriteL(SCachePage& page)
+		{
+		TPageChange change=page.iPage[0].iChange;
+		WriteL(page.iPage[0].iRef,&page.iPage[1],change);
+		}
+	void CallProtectedReadL(SCachePage& page)
+		{
+		ReadL(page.iPage[0].iRef,&page.iPage[1]);
+		}
+	TPageRef CallProtectedExtendL(SCachePage& page)
+		{
+		ExtendL(&page.iPage[1],EPageReclaimable);
+		return page.iPage[0].iRef;
+		}
+	};
+
+/**
+@SYMTestCaseID          PDS-STORE-CT-4010
+@SYMTestCaseDesc	    RFilePagePool protected API tests
+@SYMTestPriority 	    High
+@SYMTestActions  	    Tests for read and write and extend operations
+@SYMTestExpectedResults Cache pages should be properly written and properly read from RFilePagePoolTestClass
+@SYMDEF                 DEF135804
+*/
+LOCAL_C void test5L()
+	{
+	SCachePage page;
+	page.iPage[0].iRef = 1;
+	page.iPage[0].iChange=EPageNoChange;
+	
+	RFilePagePoolTestClass fpp;
+	RFs fs;
+	fs.Connect();
+	fs.MkDirAll(KPageFilePathOnly);
+	fs.Delete(KPageFilePath);
+	CPageCache* pcache = CPageCache::NewLC(2);
+	//creating file
+	TheTest.Printf(_L("Creating file "));
+	TInt err = fpp.Create(fs, KPageFilePath, EFileWrite);
+	TEST2(err, KErrNone);
+	fpp.Set(*pcache);
+	TheTest.Printf(_L("-> File created -> Testing protected API "));
+	TRAP(err, fpp.CallProtectedWriteL(page));
+	TEST2(err, KErrNone);
+	TheTest.Printf(_L("-> CallProtectedWriteL() done "));
+	TRAP(err, fpp.CallProtectedReadL(page));
+	TEST2(err, KErrNone);
+	TheTest.Printf(_L("-> CallProtectedReadL() done "));
+	TRAP(err, fpp.CallProtectedExtendL(page));
+	TEST2(err, KErrNone);
+	TheTest.Printf(_L("-> CallProtectedExtendL() done -> Closing"));
+	fpp.Close();
+	TheTest.Printf(_L("-> Closed "));
+	CleanupStack::PopAndDestroy(pcache);
+	fs.Close();
+	}
+
+const TInt KCachePages=16;
+
+LOCAL_C void testallL(RStorePagePool& aPool)
+	{
+	TheTest.Start(_L("Connecting page pool"));
+	aPool.Set(*CPageCache::NewLC(KCachePages));
+	aPool.Create(*TheStore);
+	TheTest.Next(_L("Basic operations"));
+	test1L(aPool);
+	TheTest.Next(_L("Large set TUint32"));
+	test2L(aPool);
+	aPool.Discard();
+	aPool.ReclaimAllL();
+	aPool.Close();
+	TheTest.Next(_L("Tokens and streaming"));
+	test3L(aPool);
+	CleanupStack::PopAndDestroy();	//cache
+	TheTest.Next(_L("PDS-STORE-CT-4009: RFilePagePool tests"));
+	test4L();
+	TheTest.Next(_L("PDS-STORE-CT-4010: RFilePagePool protected API tests"));
+	test5L();
+	TheTest.End();
+	}
+
+/**
+@SYMTestCaseID          PDS-STORE-CT-4021
+@SYMTestCaseDesc	    RStorePagePool protected API tests
+@SYMTestPriority 	    High
+@SYMTestActions  	    Tests for different constructors
+@SYMTestExpectedResults Objects must be created successfully
+@SYMDEF                 DEF135804
+*/
+LOCAL_C void testconstructionL(CPBEncryptSet* aKey)
+	{
+	TheTest.Next(_L("PDS-STORE-CT-4021: RStorePagePool protected API tests"));
+	CPageCache* pcache = CPageCache::NewLC(KCachePages);
+	TStorePagePoolToken token;
+	RStorePagePool poolcached(*pcache);
+	poolcached.Create(*TheStore);
+	test1L(poolcached);
+	poolcached.Discard();
+	poolcached.ReclaimAllL();
+	poolcached.Close();	
+	RStorePagePool poolstream(*TheStore);
+	poolstream.Set(*pcache);
+	test1L(poolstream);
+	poolstream.Discard();
+	poolstream.ReclaimAllL();
+	poolstream.Close();
+	RStorePagePool poolstreamtoken(*TheStore, token);
+	poolstreamtoken.Set(*pcache);
+	test1L(poolstreamtoken);	
+	poolstreamtoken.Close();
+	RSecureStorePagePool securepoolcached( *pcache, *aKey );
+	securepoolcached.Create(*TheStore);
+	test1L(securepoolcached);
+	securepoolcached.Discard();
+	securepoolcached.ReclaimAllL();
+	securepoolcached.Close();
+	
+	
+	CleanupStack::PopAndDestroy();
+	
+	}
+
+LOCAL_C void doMainL()
+	{
+	TheTest.Start(_L("Store PagePool"));
+	TParsePtrC parse(KFileLocationSpec);
+	
+	TheStore=CPermanentFileStore::ReplaceLC(TheFs,parse.NameAndExt(),EFileRead|EFileWrite);
+	TheStore->SetTypeL(TheStore->Layout());
+	RStorePagePool pool1;
+	testallL(pool1);
+	TheTest.Next(_L("Secure PagePool"));
+
+	CPBEncryptSet* key = CPBEncryptSet::NewLC(_L("the password"));
+	RSecureStorePagePool pool2(*key);
+	testallL(pool2);
+
+
+	testconstructionL(key);
+	
+	CleanupStack::PopAndDestroy(key);
+	TheStore->CommitL();
+	CleanupStack::PopAndDestroy();	// store
+	}
+
+//
+// Prepare the test directory.
+//
+LOCAL_C void setupTestDirectory()
+    {
+	TInt r=TheFs.Connect();
+	TEST2(r, KErrNone);
+//
+	TDriveUnit drive(static_cast<TUint>(RFs::GetSystemDrive()));	
+	TParse parse;
+	parse.Set(drive.Name(), &KFileLocationSpec, NULL);
+	
+	r=TheFs.MkDir(parse.DriveAndPath());
+	TEST(r==KErrNone||r==KErrAlreadyExists);
+	r=TheFs.SetSessionPath(parse.DriveAndPath());
+	TEST2(r, KErrNone);
+	}
+
+//
+// Initialise the cleanup stack.
+//
+LOCAL_C void setupCleanup()
+    {
+	TheTrapCleanup=CTrapCleanup::New();
+	TEST(TheTrapCleanup!=NULL);
+	TRAPD(r,\
+		{\
+		for (TInt i=KTestCleanupStack;i>0;i--)\
+			CleanupStack::PushL((TAny*)1);\
+		TEST2(r, KErrNone);\
+		CleanupStack::Pop(KTestCleanupStack);\
+		});
+	TEST2(r, KErrNone);
+	}
+
+
+
+LOCAL_C void DeleteTestFiles()
+	{
+
+	RFs fs;
+	TInt err = fs.Connect();
+	if(err == KErrNone)
+		{
+		CDir* dir;
+		fs.GetDir(KPageFilePathOnly, KEntryAttNormal , ESortNone, dir);
+		for(TInt i=0; i< dir->Count();i++)
+			{
+			CDir& rdir = *dir;
+			TFileName tf (KPageFilePathOnly);
+			tf.Append(rdir[i].iName);
+			err = fs.Delete( tf );
+			if (err != KErrNone)
+				{
+				RDebug::Print(_L("Error %d deleting file \"%S\".\n"), err, &(rdir[i].iName));
+				}
+			else
+				RDebug::Print(_L("File \"%S\" removed.\n"), &(rdir[i].iName));
+			}
+		delete dir;
+		err = fs.RmDir(KPageFilePathOnly);
+		if (err != KErrNone)
+			{
+			RDebug::Print(_L("Error %d deleting folder \"%S\".\n"), err, &KPageFilePathOnly);
+			}
+		fs.Close();
+		}
+	else
+		{
+		RDebug::Print(_L("Error %d connecting file session.\n"), err);
+		}
+	}
+
+LOCAL_C void DeleteDataFile(const TDesC& aFullName)
+	{
+	RFs fsSession;
+	TInt err = fsSession.Connect();
+	if(err == KErrNone)
+		{
+		TEntry entry;
+		if(fsSession.Entry(aFullName, entry) == KErrNone)
+			{
+			RDebug::Print(_L("Deleting \"%S\" file.\n"), &aFullName);
+			err = fsSession.SetAtt(aFullName, 0, KEntryAttReadOnly);
+			if(err != KErrNone)
+				{
+				RDebug::Print(_L("Error %d changing \"%S\" file attributes.\n"), err, &aFullName);
+				}
+			err = fsSession.Delete(aFullName);
+			if(err != KErrNone)
+				{
+				RDebug::Print(_L("Error %d deleting \"%S\" file.\n"), err, &aFullName);
+				}
+			}
+		fsSession.Close();
+		}
+	else
+		{
+		RDebug::Print(_L("Error %d connecting file session. File: %S.\n"), err, &aFullName);
+		}
+	}
+
+GLDEF_C TInt E32Main()
+	{
+	TheTest.Title();
+	setupTestDirectory();
+	setupCleanup();
+	__UHEAP_MARK;
+//
+	TRAPD(r,doMainL());
+	TEST2(r, KErrNone);
+
+	//deletion of data files must be before call to .End() - DEF047652
+	TDriveUnit drive(static_cast<TUint>(RFs::GetSystemDrive()));	
+		TParse parse;
+		parse.Set(drive.Name(), &KFileLocationSpec, NULL);
+		::DeleteDataFile(parse.FullName());
+		::DeleteTestFiles();
+		
+	TheTest.End();
+//
+	__UHEAP_MARKEND;
+
+	delete TheTrapCleanup;
+	TheFs.Close();
+	TheTest.Close();
+	return 0;
+	}
+