kerneltest/e32test/buffer/t_bseg.cpp
changeset 0 a41df078684a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/buffer/t_bseg.cpp	Mon Oct 19 15:55:17 2009 +0100
@@ -0,0 +1,468 @@
+// Copyright (c) 1994-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:
+// e32test\buffer\t_bseg.cpp
+// Overview:
+// Test all aspects of the CBufSeg class.
+// API Information:
+// CBufSeg.
+// Details:
+// - Create a segmented dynamic buffer of specified size.
+// - Test all operations of CBufSeg class and see if methods are implemented -- 
+// including NewL, Reset, Size, InsertL, Delete, Ptr, BackPtr, Read, Write and Compress.
+// - Test CBufSeg constructor is as expected.
+// - Insert data into the segmented dynamic buffer and verify that InsertL method
+// is as expected using the Read and Write methods.
+// - Delete all data using Reset method and check size is zero.
+// - Test InsertL, Read, Write and Length methods.
+// - Test Ptr, Free, Size, Backptr and SetReserveL methods are as expected.
+// - Check self consistancy of segment lengths, and check contents of segmented 
+// buffer using Ptr() and BackPtr().
+// - Verify the size of the of the test buffers are correct.
+// - Insert data into the buffer, delete some data from the beginning, middle and end
+// then check for results as expected. 
+// - Verify the data in the buffer before and after Compress method is as expected.
+// Platforms/Drives/Compatibility:
+// All 
+// Assumptions/Requirement/Pre-requisites:
+// Failures and causes:
+// Base Port information:
+// 
+//
+
+#include <e32test.h>
+
+class TBufSegLink : public TDblQueLink
+	{
+public:
+	inline TBufSegLink() : iLen(0) {}
+	inline TBufSegLink* Next() const {return((TBufSegLink*)iNext);}
+	inline TBufSegLink* Prev() const {return((TBufSegLink*)iPrev);}
+public:
+	TInt iLen;
+	};
+
+class TestCBufSeg
+	{
+public:
+	TestCBufSeg() : iDummy(0) {};
+	void Test1(); 	// Test all operations of the class.
+	void Test2();	// Inherited Methods
+	void Test3();	// Insert	
+	void Test4();	// Delete
+	void Test5();	// Compress
+	void Test6L();	// borderlines
+protected:
+	TInt iDummy;
+	static const TInt SegLen;
+	void CheckSeg(const CBufSeg*);
+	void CheckContents1(CBufSeg* const);
+	void CheckContents2(CBufSeg* const);
+	};
+
+const TInt TestCBufSeg::SegLen=64;
+
+LOCAL_D RTest test(_L("T_BSEG"));
+
+class CSpy : public CBufBase
+	{
+public:
+	~CSpy();
+protected:
+	CSpy(TInt anExpandSize);
+public:
+    TDblQue<TBufSegLink> iQue;
+	TBufSegLink* iSeg;
+	TInt iBase;
+	TInt iOffset;
+	};
+
+GLDEF_C void TestCBufSeg::CheckSeg(const CBufSeg* bf)
+//
+// Check Self consistancy of segment lengths
+//
+	{
+
+	if (bf->Size()==0)
+		return;
+	TInt sum=0;
+	TBufSegLink* p1=((CSpy*)bf)->iQue.First();
+	while (!((CSpy*)bf)->iQue.IsHead(p1))
+		{
+		test(p1->iLen<=bf->Size());
+		sum+=p1->iLen;
+		p1=p1->Next();
+		} 
+	test(sum==bf->Size());
+	sum=0;
+	p1=((CSpy*)bf)->iQue.Last();
+	while (!((CSpy*)bf)->iQue.IsHead(p1))
+		{
+		test(p1->iLen<=bf->Size());
+		sum+=p1->iLen;
+		p1=p1->Prev();
+		}
+	test(sum==bf->Size());
+	}
+
+GLDEF_C void TestCBufSeg::CheckContents1(CBufSeg* const bf)
+//
+// Check contents of segmented buffer using Ptr()
+//
+	{
+
+	TInt sum=0;
+	TInt nbytes=bf->Size();
+	for (TInt pos=0;pos<nbytes;)
+		{
+		TPtr8 p=bf->Ptr(pos);
+		TInt len=p.Length();
+		TInt8* pT=(TInt8*)p.Ptr();
+		for (TInt i=0;i<len;i++)
+			sum+=*pT++;
+		test(sum==0);
+		pos+=len;
+		}
+	}
+
+GLDEF_C void TestCBufSeg::CheckContents2(CBufSeg* const bf)
+//
+// Check contents of segmented buffer using BackPtr()
+//
+	{
+
+	TInt sum=0;
+	TInt nbytes=bf->Size();
+	for(TInt pos=nbytes;pos>0;)
+		{
+		TPtr8 p=bf->BackPtr(pos);
+		TInt len=p.Length();
+		TInt8* pT=(TInt8*)p.Ptr();
+		for (TInt i=0;i<len;i++)
+			sum+=*pT++;
+		pos-=len;
+		}
+	test(sum==0);
+	}
+
+GLDEF_C void TestCBufSeg::Test1()
+//
+// Test all operations of BufSeg class
+//
+	{
+
+	test.Start(_L("Test all operations of CBufSeg"));
+	CBufSeg* bf=(CBufSeg*)CBufSeg::NewL(100);
+	bf->Reset();
+	bf->Size();
+	bf->InsertL(0,TPtrC8((TText8*)"Hello World"));
+	bf->Delete(0,5);
+	TText8* tp=(TText8*)bf->Ptr(3).Ptr();
+	tp=(TText8*)bf->BackPtr(3).Ptr();
+	TBuf8<0x20> txt;
+	bf->Read(2,txt,2);
+	bf->Write(2,txt,2);
+	bf->Compress();
+	delete bf;
+	test.End();
+	}
+			
+GLDEF_C void TestCBufSeg::Test2()
+//
+// Test all inherited methods
+//
+	{
+
+	TBuf8<0x40> tb1=(TText8*)"Hello World";
+	TBuf8<0x40> tb2=(TText8*)"String number two";
+	TBuf8<0x40> tb3;
+	test.Start(_L("Free,Size,Read,Write,Reset"));
+	CBufSeg* bf=(CBufSeg*)CBufSeg::NewL(SegLen);
+	test(bf->Size()==0);
+	bf->InsertL(0,tb1);
+	test(bf->Size()==tb1.Length());
+	bf->Read(6,tb3,5);
+	test(tb3==tb1.Right(5));
+	bf->Write(1,tb2,6);
+	bf->Read(0,tb3,bf->Size());
+	test(tb3==TPtrC8((TText8*)"HStringorld"));
+	bf->Reset();
+	test(bf->Size()==0);
+	while (bf->Size()<400)
+		{
+		bf->InsertL(bf->Size(),tb1);
+		bf->InsertL(bf->Size(),tb2);
+		}
+	TInt i=0;
+	while (i<400)
+		{
+		bf->Read(i,tb3,tb1.Size());
+		test(tb3==tb1);
+		i+=tb1.Length();
+		bf->Read(i,tb3,tb2.Size());
+		test(tb3==tb2);
+		i+=tb2.Length();
+		}
+	i=0;
+	while (i<400)
+		{
+		bf->Write(i,tb2);
+		i+=tb2.Length();
+		bf->Write(i,tb1);
+		i+=tb1.Length();
+		}
+	i=0;
+	while (i<400)
+		{
+		bf->Read(i,tb3,tb2.Size());
+		test(tb3==tb2);
+		i+=tb2.Length();
+		bf->Read(i,tb3,tb1.Size());
+		test(tb3==tb1);
+		i+=tb1.Length();
+		}
+	delete bf;
+	test.End();
+	}
+
+GLDEF_C void TestCBufSeg::Test3()
+//
+//	Test input methods
+//
+	{
+
+	TInt8 bb[1000];
+	TInt nbytes;
+	test.Start(_L("InsertL"));
+	CBufSeg* bf1=(CBufSeg*)CBufSeg::NewL(SegLen);
+	CBufSeg* bf2=(CBufSeg*)CBufSeg::NewL(SegLen);
+	CBufSeg* bf3=(CBufSeg*)CBufSeg::NewL(SegLen);
+	nbytes=0;
+	TInt k;
+	for(TInt j=0;j<20;j++)
+		{
+		for(TInt i=0;i<10*j;i+=2)
+			{
+			k=i%128;
+			bb[i]=(TInt8)k;
+			bb[i+1]=(TInt8)-k;
+			}
+		bf1->InsertL(bf1->Size()/3*2,&bb[0],10*j);
+		CheckSeg(bf1);
+		CheckContents1(bf1);
+		CheckContents2(bf1);
+		bf2->InsertL(bf2->Size(),&bb[0],10*j);
+		CheckSeg(bf2);
+		CheckContents1(bf2);
+		CheckContents2(bf2);
+		bf3->InsertL(0,&bb[0],10*j);
+		CheckSeg(bf3);
+		CheckContents1(bf3);
+		CheckContents2(bf3);
+		nbytes+=10*j;
+		}
+	test(nbytes==bf1->Size());
+	test(nbytes==bf2->Size());
+	test(nbytes==bf3->Size());
+	delete bf1;
+	delete bf2;
+	delete bf3;
+	test.End();
+	}
+
+GLDEF_C void TestCBufSeg::Test4()
+//
+// Delete
+// 
+	{
+	TInt8 bb[1000];
+
+	test.Start(_L("Delete"));
+	CBufSeg* bf1=(CBufSeg*)CBufSeg::NewL(SegLen);
+	CBufSeg* bf2=(CBufSeg*)CBufSeg::NewL(SegLen);
+	CBufSeg* bf3=(CBufSeg*)CBufSeg::NewL(SegLen);
+	TInt nbytes=0;
+	TInt k;
+	for(TInt j=0;j<20;j++)
+		{
+		for(TInt i=0;i<10*j;i+=2)
+			{
+			k=i%128;
+			bb[i]=(TInt8)k;
+			bb[i+1]=(TInt8)-k;
+			}
+		bf1->InsertL(bf1->Size()/3*2,&bb[0],10*j);
+		bf2->InsertL(bf2->Size(),&bb[0],10*j);
+		bf3->InsertL(0,&bb[0],10*j);
+		nbytes+=10*j;
+		}
+	TInt len=34;
+	TInt aLength;
+	while (nbytes>len)
+		{
+		for (TInt pos=0;pos<nbytes;pos+=44)
+		{
+			len=((len+17)%23)*2;
+			if (len>nbytes-pos)
+				len=nbytes-pos;
+			bf1->Delete(pos,len);
+			CheckSeg(bf1);
+			CheckContents1(bf1);
+			CheckContents2(bf1);
+			aLength=bf2->Ptr(0).Length();
+			aLength=((aLength>len) ? aLength : len);
+			bf2->Delete(aLength-len,len);
+			CheckSeg(bf2);
+			CheckContents1(bf2);
+			CheckContents2(bf2);
+			bf3->Delete(0,len);
+			CheckSeg(bf3);
+			CheckContents1(bf3);
+			CheckContents2(bf3);
+			nbytes-=len;
+			test(nbytes==bf1->Size());
+			test(nbytes==bf2->Size());
+			test(nbytes==bf3->Size());
+			}
+		}
+	delete bf1;
+	delete bf2;
+	delete bf3;
+	test.End();
+	}
+
+GLDEF_C void TestCBufSeg::Test5()
+//
+// Compress
+// 
+	{
+	TInt8 bb[1000];
+
+	test.Start(_L("Compress"));
+	CBufSeg* bf1=(CBufSeg*)CBufSeg::NewL(SegLen);
+	CBufSeg* bf2=(CBufSeg*)CBufSeg::NewL(SegLen);
+	CBufSeg* bf3=(CBufSeg*)CBufSeg::NewL(SegLen);
+	TInt nbytes=0;
+	TInt k;
+	for(TInt j=0;j<20;j++)
+		{
+		for(TInt i=0;i<10*j;i+=2)
+			{
+			k=i%128;
+			bb[i]=(TInt8)k;
+			bb[i+1]=(TInt8)-k;
+			}
+		bf1->InsertL(bf1->Size()/3*2,&bb[0],10*j);
+		bf2->InsertL(bf2->Size(),&bb[0],10*j);
+		bf3->InsertL(0,&bb[0],10*j);
+		nbytes+=10*j;
+		}
+	TInt len=34;
+	TInt aLength;
+	while (nbytes>len)
+		{
+		for (TInt pos=0;pos<nbytes;pos+=44)
+		{
+			if (len>nbytes-pos)
+				len=nbytes-pos;
+			bf1->Delete(pos,len);
+			bf1->Compress();
+			CheckSeg(bf1);
+			CheckContents1(bf1);
+			CheckContents2(bf1);
+			aLength=bf2->Ptr(0).Length();
+			aLength=((aLength>len)? aLength : len);
+			bf2->Delete(aLength-len,len);
+			bf2->Compress();
+			CheckSeg(bf2);
+			CheckContents1(bf2);
+			CheckContents2(bf2);
+			bf3->Delete(0,len);
+			bf3->Compress();
+			CheckSeg(bf3);
+			CheckContents1(bf3);
+			CheckContents2(bf3);
+			nbytes-=len;
+			test(nbytes==bf1->Size());
+			test(nbytes==bf2->Size());
+			test(nbytes==bf3->Size());
+			}
+		}
+	delete bf1;
+	delete bf2;
+	delete bf3;
+	test.End();
+	}
+
+void TestCBufSeg::Test6L()
+	{
+	test.Start(_L("Test compress frees empty cells"));
+	__UHEAP_MARK;
+	TUint8 alphabet[27] = "abcdefghijklmnopqrstuvwxyz";
+	CBufSeg* buf = CBufSeg::NewL(10);
+	CleanupStack::PushL(buf);
+	buf->InsertL(0, alphabet, 16);	// "abcdefghij" ++ "klmnop"
+	buf->Delete(5, 5);			// "abcde" ++ "klmnop"
+	buf->Delete(10, 1);			// "abcde" ++ "klmno"
+	buf->Compress();				// "abcdefklmno". i.e. empty cell should be freed.
+	CleanupStack::PopAndDestroy(buf);
+	__UHEAP_MARKEND;
+	test.End();
+	}
+
+LOCAL_C void test_CBufSeg()
+//
+// Test the BufSeg class
+//
+	{
+
+	TestCBufSeg b;
+	test.Start(_L("All operations"));
+	b.Test1();
+	test.Next(_L("Inherited Methods"));
+	b.Test2();
+	test.Next(_L("Insert"));
+	b.Test3();
+	test.Next(_L("Delete"));
+	b.Test4();
+	test.Next(_L("Compress"));
+	b.Test5();
+	test.Next(_L("Bordeline cases"));
+	TRAPD(r,b.Test6L());
+	test(r==KErrNone);
+	//
+	test.End();
+	}
+
+GLDEF_C TInt E32Main()
+//
+// Test the ADT segmented varray.
+//
+	{
+	
+	test.Title();
+	__UHEAP_MARK;
+//
+// Install a trap handler
+//
+	CTrapCleanup* trapHandler=CTrapCleanup::New();
+	test(trapHandler!=NULL);
+//	CleanupStack::NextLevel();
+	test.Start(_L("class CBufSeg"));
+	test_CBufSeg();
+	delete trapHandler;
+	__UHEAP_MARKEND;
+	test.End();
+	return(0);
+	}
+