kerneltest/e32test/system/t_kucopy.cpp
author Tom Cosgrove <tom.cosgrove@nokia.com>
Fri, 28 May 2010 16:29:07 +0100
changeset 30 8aab599e3476
parent 0 a41df078684a
permissions -rw-r--r--
Fix for bug 2283 (RVCT 4.0 support is missing from PDK 3.0.h) Have multiple extension sections in the bld.inf, one for each version of the compiler. The RVCT version building the tools will build the runtime libraries for its version, but make sure we extract all the other versions from zip archives. Also add the archive for RVCT4.

// 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 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\system\t_kucopy.cpp
// Test copying between kernel and user side.
// 
//

#define __E32TEST_EXTENSION__

#include <e32test.h>
#include "d_kucopy.h"
#include "../mmu/mmudetect.h"

//#define QUICK

_LIT(KLddFileName,"D_KUCOPY.LDD");
_LIT(KLitKernExec,"KERN-EXEC");

RTest test(_L("T_KUCOPY"));
RKUCopy KU;
TInt BufSize;
TInt RandSize;
TUint8* Buf1;
TUint8* Buf2;
TUint8* Random;
TBool KernProt=EFalse;

_LIT8(KTest8_1,"1");
_LIT8(KTest8_2,"Test2");
_LIT8(KTest8_3,"extensionality emptyset pairset separation powerset unionset infinity foundation replacement choice");
_LIT8(KTest8_4,"And darkness and decay and the red death held illimitable dominion over all.");

_LIT16(KTest16_1,"39");
_LIT16(KTest16_2,"Test16");
_LIT16(KTest16_3,"extensionality emptyset pairset separation powerset unionset infinity foundation replacement choice.");
_LIT16(KTest16_4,"And darkness and decay and the red death held illimitable dominion over all.");

static const TDesC8* const TestStrings8[]=
	{
	&KTest8_1,
	&KTest8_2,
	&KTest8_3,
	&KTest8_4,
	};

static const TDesC16* const TestStrings16[]=
	{
	&KTest16_1,
	&KTest16_2,
	&KTest16_3,
	&KTest16_4,
	};

#define NTESTS8		((TInt)(sizeof(TestStrings8)/sizeof(const TDesC8*)))
#define NTESTS16	((TInt)(sizeof(TestStrings16)/sizeof(const TDesC16*)))

enum TTest
	{
	EPut,
	EGet,
	EPut32,
	EGet32,
	ESet,
	EDesPut8,
	EDesGet8,
	EDesInfo8,
	EDesPut16,
	EDesGet16,
	EDesInfo16,
	};

void DoPutGetTest(TInt aSrcOffset, TInt aDestOffset, TInt aLen, TTest aTest)
	{
	// Use the first BufSize of random data as background, the rest as copy data.
	// Use Buf1 as target
//	test.Printf(_L("s=%4d d=%4d l=%4d t=%d\n"),aSrcOffset,aDestOffset,aLen,aTest);
	switch (aTest)
		{
		case EPut:
			Mem::Move(Buf1,Random,BufSize);
			KU.Put(Buf1+aDestOffset,aSrcOffset+BufSize,aLen);
			break;
		case EGet:
			KU.Get(Random+BufSize+aSrcOffset,aDestOffset,aLen);
			KU.Read(Buf1);
			break;
		case EPut32:
			Mem::Move(Buf1,Random,BufSize);
			KU.Put32((TUint32*)(Buf1+aDestOffset),aSrcOffset+BufSize,aLen);
			break;
		case EGet32:
			KU.Get32((const TUint32*)(Random+BufSize+aSrcOffset),aDestOffset,aLen);
			KU.Read(Buf1);
			break;
		default:
			User::Panic(_L("PutGetTest"),aTest);
		}

	// Should now have:
	// Buf1[0...aDestOffset-1]=Random[0...aDestOffset-1]
	// Buf1[aDestOffset...aDestOffset+aLen-1]=Random[BufSize+aSrcOffset...BufSize+aSrcOffset+aLen-1]
	// Buf1[aDestOffset+aLen...BufSize-1]=Random[aDestOffset+aLen...BufSize-1]
	test(Mem::Compare(Buf1,aDestOffset,Random,aDestOffset)==0);
	test(Mem::Compare(Buf1+aDestOffset,aLen,Random+BufSize+aSrcOffset,aLen)==0);
	test(Mem::Compare(Buf1+aDestOffset+aLen,BufSize-aDestOffset-aLen,Random+aDestOffset+aLen,BufSize-aDestOffset-aLen)==0);
	}

void DoSetTest(TInt aOffset, TInt aLen, TUint8 aValue)
	{
	Mem::Move(Buf1,Random,BufSize);
	KU.Set(Buf1+aOffset,aLen,aValue);
	test(Mem::Compare(Buf1,aOffset,Random,aOffset)==0);
	TUint8* p=Buf1+aOffset;
	TUint8* pE=p+aLen;
	while (p<pE)
		test(*p++==aValue);
	test(Mem::Compare(Buf1+aOffset+aLen,BufSize-aOffset-aLen,Random+aOffset+aLen,BufSize-aOffset-aLen)==0);
	}

void TestDesGet8(const TDesC8& aSrc)
	{
	TPtr8 dest(Buf2,0,BufSize);
	KU.DesGet(dest,aSrc);
	test(dest==aSrc);
	}

void TestDesGet8()
	{
	TInt i;
	for (i=0; i<NTESTS8; ++i)
		{
		const TDesC8* orig=TestStrings8[i];
		TestDesGet8(*orig);	// test EBufC
		TBuf8<256> buf=*orig;
		TestDesGet8(buf);	// test EBuf
		TPtrC8 ptrc(orig->Ptr(),orig->Length());
		TestDesGet8(ptrc);	// test EPtrC
		TPtr8 ptr((TUint8*)orig->Ptr(),orig->Length(),orig->Length());
		TestDesGet8(ptr);	// test EPtr
		HBufC8* pH=orig->Alloc();
		test(pH!=NULL);
		TPtr8 bufCptr(pH->Des());
		TestDesGet8(bufCptr);	// test EBufCPtr
		User::Free(pH);
		}
	}

void TestDesPut8(TDesC8& aDest, const TDesC8* aExtraDest, const TDesC8& aSrc)
	{
	KU.DesPut((TDes8&)aDest,aSrc);
	test(aDest==aSrc);
	if (aExtraDest)
		test(*aExtraDest==aSrc);	// for testing EBufCPtr
	}

void TestDesPut8()
	{
	TInt i;
	for (i=0; i<NTESTS8; ++i)
		{
		const TDesC8* orig=TestStrings8[i];
		TBuf8<256> buf;
		TestDesPut8(buf,NULL,*orig);	// test EBuf
		Mem::FillZ((TAny*)buf.Ptr(),256);
		TPtr8 ptr((TUint8*)buf.Ptr(),0,256);
		TestDesPut8(ptr,NULL,*orig);	// test EPtr
		HBufC8* pH=HBufC8::New(256);
		test(pH!=NULL);
		TPtr8 bufCptr(pH->Des());
		TestDesPut8(bufCptr,pH,*orig);	// test EBufCPtr
		User::Free(pH);
		}
	}

void TestDesInfo8(const TDesC8& aDes, TInt aLength, TInt aMaxLength, const TUint8* aPtr)
	{
	SDesInfo info;
	KU.DesInfo(aDes,info);
	test(aLength==info.iLength);
	test(aMaxLength==info.iMaxLength);
	test((TAny*)aPtr==info.iPtr);
	}

void TestDesInfo8()
	{
	TInt i;
	for (i=0; i<NTESTS8; ++i)
		{
		const TDesC8* orig=TestStrings8[i];
		TestDesInfo8(*orig,orig->Length(),-1,orig->Ptr());	// test EBufC
		TBuf8<256> buf;
		TestDesInfo8(buf,0,256,buf.Ptr());				// test EBuf
		buf=*orig;
		TestDesInfo8(buf,orig->Length(),256,buf.Ptr());	// test EBuf
		TBuf8<203> buf2;
		TestDesInfo8(buf2,0,203,buf2.Ptr());			// test EBuf
		buf2=*orig;
		TestDesInfo8(buf2,orig->Length(),203,buf2.Ptr());	// test EBuf
		TPtrC8 ptrc(orig->Ptr(),orig->Length());
		TestDesInfo8(ptrc,orig->Length(),-1,orig->Ptr());	// test EPtrC
		TPtr8 ptr((TUint8*)orig->Ptr(),orig->Length(),orig->Length());
		TestDesInfo8(ptr,orig->Length(),orig->Length(),orig->Ptr());	// test EPtr
		HBufC8* pH=orig->Alloc();
		test(pH!=NULL);
		TPtr8 bufCptr(pH->Des());
		TestDesInfo8(*pH,orig->Length(),-1,pH->Ptr());
		TestDesInfo8(bufCptr,orig->Length(),User::AllocLen(pH)-sizeof(TDesC8),pH->Ptr());
		User::Free(pH);
		}
	}

void RunTestInThread(TThreadFunction aFn, TAny* aParameter, const TDesC* aPanicCat, TInt aExitCode, TInt aLine)
	{
	test.Printf(_L("Line %d\n"),aLine);
	RThread t;
	TInt r=t.Create(KNullDesC(),aFn,0x2000,NULL,aParameter);
	test(r==KErrNone);
	TRequestStatus s;
	t.Logon(s);
	t.Resume();
	User::WaitForRequest(s);
	if (aPanicCat)
		{
		test(t.ExitType()==EExitPanic);
		test(t.ExitCategory()==*aPanicCat);
		test(t.ExitReason()==aExitCode);
		}
	else
		{
		test(t.ExitType()==EExitKill);
		test(t.ExitReason()==aExitCode);
		}
	CLOSE_AND_WAIT(t);
	}

TInt DesGet8Thread(TAny* aPtr)
	{
	TBuf8<256> dest;
	KU.DesGet(dest, *(const TDesC8*)aPtr);
	return 0;
	}

TInt DesPut8Thread(TAny* aPtr)
	{
	KU.DesPut(*(TDes8*)aPtr,KTest8_4);
	return 0;
	}

TInt DesInfo8Thread(TAny* aPtr)
	{
	SDesInfo info;
	KU.DesInfo(*(TDesC8*)aPtr,info);
	return 0;
	}

void TestErrors()
	{
	TBool jit=User::JustInTime();
	User::SetJustInTime(EFalse);
	TUint8* Kern=KU.KernelBufferAddress();
	TUint x=0xffffffff;
	TBuf8<256> ubuf;
	TPtrC8 uptrc(Buf1,100);
	TPtrC8 kptrc(Kern,1);
	TPtr8 kptr(Kern,10,256);
	RunTestInThread(DesGet8Thread,&x,&KLitKernExec,EKUDesInfoInvalidType,__LINE__);
	RunTestInThread(DesGet8Thread,&ubuf,NULL,KErrNone,__LINE__);
	RunTestInThread(DesGet8Thread,&ubuf,NULL,KErrNone,__LINE__);
	if (KernProt)
		{
		RunTestInThread(DesGet8Thread,Kern,&KLitKernExec,ECausedException,__LINE__);
		RunTestInThread(DesGet8Thread,&kptrc,&KLitKernExec,ECausedException,__LINE__);
		RunTestInThread(DesGet8Thread,&kptr,&KLitKernExec,ECausedException,__LINE__);
		}
	RunTestInThread(DesPut8Thread,&x,&KLitKernExec,EKUDesInfoInvalidType,__LINE__);
	RunTestInThread(DesPut8Thread,&ubuf,NULL,KErrNone,__LINE__);
	RunTestInThread(DesPut8Thread,&uptrc,&KLitKernExec,EKUDesSetLengthInvalidType,__LINE__);
	if (KernProt)
		{
		RunTestInThread(DesPut8Thread,Kern,&KLitKernExec,ECausedException,__LINE__);
		RunTestInThread(DesPut8Thread,&kptrc,&KLitKernExec,EKUDesSetLengthInvalidType,__LINE__);
		RunTestInThread(DesPut8Thread,&kptr,&KLitKernExec,ECausedException,__LINE__);
		}
	RunTestInThread(DesInfo8Thread,&x,&KLitKernExec,EKUDesInfoInvalidType,__LINE__);
	RunTestInThread(DesInfo8Thread,&ubuf,NULL,KErrNone,__LINE__);
	RunTestInThread(DesInfo8Thread,&uptrc,NULL,KErrNone,__LINE__);
	RunTestInThread(DesInfo8Thread,&kptrc,NULL,KErrNone,__LINE__);
	RunTestInThread(DesInfo8Thread,&kptr,NULL,KErrNone,__LINE__);
	if (KernProt)
		{
		RunTestInThread(DesInfo8Thread,Kern,&KLitKernExec,ECausedException,__LINE__);
		}

	User::SetJustInTime(jit);
	}

void RequestCompleteBadPointer(TUint aBadAddress)
	{
	TRequestStatus* badStatus = (TRequestStatus*)aBadAddress;
	test.Printf(_L("Test Kern::RequestComplete to %08x\n"), aBadAddress);
	KU.RequestComplete(badStatus);
	test.Printf(_L("Test Kern::RequestComplete to %08x (in current thread)\n"), aBadAddress);
	KU.RequestCompleteLocal(badStatus);

	// Check the thread hasn't been signalled
	TRequestStatus status;
	RTimer timer;
	test_KErrNone(timer.CreateLocal());
	timer.After(status, 100000); // 100ms
	test_Equal(KRequestPending, status.Int());
	User::WaitForAnyRequest();
	test_Equal(KErrNone, status.Int());
	timer.Close();	
	
	test.Printf(_L("Test Kern::QueueRequestComplete to %08x\n"), aBadAddress);
	TInt r = KU.QueueRequestComplete(badStatus);

	// Kern::QueueRequestComplete will signal even if the pointer is bad, unless:
	//  - the pointer is null
	//  - the call to Setup returned an error
	if (badStatus != NULL && r == KErrNone)
		User::WaitForAnyRequest();
	}

void TestRequestCompleteTrapped()
	{
	TRequestStatus status;
	test.Printf(_L("Test Kern::RequestComplete to %08x\n"), &status);
	status = KRequestPending;
	KU.RequestComplete(&status);
	User::WaitForRequest(status);
	test_Equal(KErrNone, status.Int());
	
	test.Printf(_L("Test Kern::RequestComplete to %08x (in current thread)\n"), &status);
	status = KRequestPending;
	KU.RequestCompleteLocal(&status);
	User::WaitForRequest(status);
	test_Equal(KErrNone, status.Int());

	test.Printf(_L("Test Kern::QueueRequestComplete to %08x\n"), &status);
	status = KRequestPending;
	KU.QueueRequestComplete(&status);
	User::WaitForRequest(status);
	test_Equal(KErrNone, status.Int());

	RequestCompleteBadPointer(0x00000000);
	RequestCompleteBadPointer(0x00000001);
	RequestCompleteBadPointer(0x00000004);
	RequestCompleteBadPointer(0x00000008);
	if (KernProt)
		{
		RequestCompleteBadPointer(0x80000000);
		RequestCompleteBadPointer(0xfffffff0);
		RequestCompleteBadPointer((TUint)KU.KernelBufferAddress());
		}
	}

GLDEF_C TInt E32Main()
	{
	test.Title();
	test.Start(_L("Load LDD"));
	TInt r=User::LoadLogicalDevice(KLddFileName);
	test(r==KErrNone || r==KErrAlreadyExists);
	test.Next(_L("Open channel"));
	r=KU.Open();
	test(r==KErrNone);
	test.Next(_L("Create chunk"));
	RChunk c;
	r=c.CreateDisconnectedLocal(0,0,0x100000);
	test(r==KErrNone);
	BufSize=KU.Length();
	RandSize=KU.RandomLength();
	test.Printf(_L("BufSize=%x, RandSize=%x\n"),BufSize,RandSize);
	r=c.Commit(0,BufSize);
	test(r==KErrNone);
	r=c.Commit(0x10000,BufSize);
	test(r==KErrNone);
	r=c.Commit(0x20000,RandSize);
	test(r==KErrNone);
	Buf1=c.Base();
	Buf2=c.Base()+0x10000;
	Random=c.Base()+0x20000;
	test.Printf(_L("Buf1 at %08x, Buf2 at %08x, Random at %08x\n"),Buf1,Buf2,Random);
	Mem::Fill(Buf1,BufSize,0xb1);
	Mem::Fill(Buf2,BufSize,0xb2);
	Mem::Fill(Random,RandSize,0x8b);
	KU.ReadRandom(Random);

	KernProt=HaveDirectKernProt();

#ifndef QUICK
	TInt s;
	TInt d;
	TInt l;
	test.Next(_L("Put/Get 1"));
	for (l=1; l<300; l+=3)
		{
		test.Printf(_L("PG1: l=%d\n"),l);
		for (s=0; s<=BufSize-l; s+=227)
			{
			for (d=0; d<=BufSize-l; d+=229)
				{
				DoPutGetTest(s,d,l,EPut);
				DoPutGetTest(s,d,l,EGet);
				}
			}
		}

	test.Next(_L("Put/Get 2"));
	for (l=1; l<300; l+=3)
		{
		test.Printf(_L("PG2: l=%d\n"),l);
		for (s=BufSize-l; s>=0; s-=227)
			{
			for (d=BufSize-l; d>=0; d-=229)
				{
				DoPutGetTest(s,d,l,EPut);
				DoPutGetTest(s,d,l,EGet);
				}
			}
		}

	test.Next(_L("Put32/Get32 1"));
	for (l=4; l<300; l+=12)
		{
		test.Printf(_L("PG32,1: l=%d\n"),l);
		for (s=0; s<=BufSize-l; s+=4*59)
			{
			for (d=0; d<=BufSize-l; d+=4*61)
				{
				DoPutGetTest(s,d,l,EPut32);
				DoPutGetTest(s,d,l,EGet32);
				}
			}
		}

	test.Next(_L("Put32/Get32 2"));
	for (l=4; l<300; l+=12)
		{
		test.Printf(_L("PG32,2: l=%d\n"),l);
		for (s=BufSize-l; s>=0; s-=4*59)
			{
			for (d=BufSize-l; d>=0; d-=4*61)
				{
				DoPutGetTest(s,d,l,EPut32);
				DoPutGetTest(s,d,l,EGet32);
				}
			}
		}
	test.Next(_L("Set"));
	for (l=1; l<300; l+=3)
		{
		test.Printf(_L("Set: l=%d\n"),l);
		for (s=0; s<=BufSize-l; s+=83)
			{
			DoSetTest(s,l,0x1b);
			DoSetTest(s,l,0xaa);
			}
		for (s=BufSize-l; s>=0; s-=79)
			{
			DoSetTest(s,l,0x1b);
			DoSetTest(s,l,0xaa);
			}
		}
#endif
	test.Next(_L("DesGet8"));
	TestDesGet8();
	test.Next(_L("DesPut8"));
	TestDesPut8();
	test.Next(_L("DesInfo8"));
	TestDesInfo8();
	test.Next(_L("Errors"));
	TestErrors();
	test.Next(_L("Test Kern::RequestComplete functions trapped"));
	TestRequestCompleteTrapped();

	c.Close();
	KU.Close();
	test.End();
	return 0;
	}