kerneltest/e32test/property/t_prop_ldd.cpp
changeset 0 a41df078684a
child 271 dc268b18d709
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/property/t_prop_ldd.cpp	Mon Oct 19 15:55:17 2009 +0100
@@ -0,0 +1,440 @@
+// Copyright (c) 2002-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:
+//
+
+#include "t_prop_ldd.h"
+#include <kernel/kernel.h>
+#include "nk_priv.h"
+
+class DPropLDevice : public DLogicalDevice
+	{
+public:
+	DPropLDevice();
+	virtual TInt Install();
+	virtual void GetCaps(TDes8& aDes) const;
+	virtual TInt Create(DLogicalChannelBase*& aChannel);
+	};
+
+class DPropLChannel : public DLogicalChannelBase
+	{
+public:
+	DPropLChannel();
+	~DPropLChannel();
+
+	virtual TInt DoCreate(TInt aUnit, const TDesC8* anInfo, const TVersion& aVer);
+	virtual TInt Request(TInt aFunction, TAny* a1, TAny* a2);
+
+private:
+	TInt Basic(RPropChannel::TBasicInfo* aInfo);
+
+	static void CompleteFn(TAny* aPtr, TInt aReason);
+	TInt iReason;
+	NFastSemaphore iSem;
+
+	};
+
+DECLARE_STANDARD_LDD()
+//
+// Create a new device
+//
+	{
+	return new DPropLDevice;
+	}
+
+DPropLDevice::DPropLDevice()
+//
+// Constructor
+//
+	{
+	//iUnitsMask=0;
+	iVersion = TVersion(1,0,1);
+	// iParseMask = 0;
+	}
+
+TInt DPropLDevice::Install()
+//
+// Install the device driver.
+//
+	{
+	TInt r = SetName(&KPropLdName);
+	return r;
+	}
+
+void DPropLDevice::GetCaps(TDes8&) const
+//
+// Return the Comm capabilities.
+//
+	{
+	}
+
+TInt DPropLDevice::Create(DLogicalChannelBase*& aChannel)
+//
+// Create a channel on the device.
+//
+	{
+	aChannel = new DPropLChannel;
+	return aChannel ? KErrNone : KErrNoMemory;
+	}
+
+DPropLChannel::DPropLChannel() 
+	{
+	NKern::FSSetOwner(&iSem, NKern::CurrentThread());
+	}
+
+TInt DPropLChannel::DoCreate(TInt /*aUnit*/, const TDesC8* /* aInfo*/ , const TVersion& aVer)
+//
+// Create the channel from the passed info.
+//
+	{
+	if (!Kern::QueryVersionSupported(TVersion(1,0,1),aVer))
+		return KErrNotSupported;
+	return KErrNone;
+	}
+
+DPropLChannel::~DPropLChannel()
+	{
+	}
+
+
+#define BASIC_ERROR(aRes, aCond) \
+	{\
+	if (!(aCond)) \
+		{ \
+		Kern::Printf("Test '" #aCond "' fails; r = %d;\n\tfile '" __FILE__ "'; line %d;\n", aRes, __LINE__); \
+		prop.Close(); \
+		return EFalse; \
+		} \
+	}
+
+void DPropLChannel::CompleteFn(TAny* aPtr, TInt aReason)
+	{ // static
+	DPropLChannel* self = (DPropLChannel*) aPtr;
+	self->iReason = aReason;
+	NKern::FSSignal(&self->iSem);
+	}
+
+TBool DPropLChannel::Basic(RPropChannel::TBasicInfo* aInfo)
+	{
+
+	TUid category = aInfo->iCategory;
+	TUint key = aInfo->iKey;
+	TUint count = aInfo->iCount;
+	RProperty::TType type = aInfo->iType;
+
+	for (TUint i = 0; i < count; ++i)
+		{
+		RPropertyRef prop;
+		TInt r = prop.Open(category, key);
+		BASIC_ERROR(r, r == KErrNotFound);
+		r = prop.Attach(category, key);
+		BASIC_ERROR(r, r == KErrNone);
+
+		//	Defines the attributes and access control for a property. This can only be done 
+		//	once for each property. Subsequent attempts to define the same property will return
+		//	KErrAlreadyExists.
+
+		TSecurityPolicy policy;
+
+		r = prop.Define(type, policy, policy);
+		BASIC_ERROR(r, r == KErrNone);
+		r = prop.Define(type, policy, policy);
+		BASIC_ERROR(r, r == KErrAlreadyExists);
+		r = prop.Delete();
+		BASIC_ERROR(r, r == KErrNone);
+
+		// Define fails with KErrArgument if wrong type or attribute was specified.
+		r = prop.Define(RProperty::ETypeLimit, policy, policy);
+		BASIC_ERROR(r, r == KErrArgument);
+
+		static _LIT_SECURITY_POLICY_PASS(KPassPolicy);
+		TSecurityPolicy badPolicy;
+		*(TInt*)&badPolicy = -1;
+
+		r = prop.Define(type, badPolicy, policy);
+		BASIC_ERROR(r, r == KErrArgument);
+		r = prop.Define(type, KPassPolicy, badPolicy);
+		BASIC_ERROR(r, r == KErrArgument);
+	
+		if (type == RProperty::EInt)
+			{
+			// Define fails with KErrArgument if aType is TInt and aPreallocate is not 0
+			r = prop.Define(type, KPassPolicy, KPassPolicy, 16);
+			BASIC_ERROR(r, r == KErrArgument);
+
+			// Following defintion the property has a default value, 0 for integer properties
+			r = prop.Define(RProperty::EInt, KPassPolicy, KPassPolicy);
+			BASIC_ERROR(r, r == KErrNone);
+			TInt value;
+			r = prop.Get(value);
+			BASIC_ERROR(r, r == KErrNone);
+			BASIC_ERROR(value, value == 0);
+			r = prop.Delete();
+			BASIC_ERROR(r, r == KErrNone);
+			}
+		else 
+			{
+			// Defne fails with KErrTooBig if aPeallocate is grater than KMaxPropertySize.
+			r = prop.Define(RProperty::EByteArray, KPassPolicy, KPassPolicy, RProperty::KMaxPropertySize);
+			BASIC_ERROR(r, r == KErrNone);
+			r = prop.Delete();
+			BASIC_ERROR(r, r == KErrNone);
+			r = prop.Define(RProperty::EByteArray, KPassPolicy, KPassPolicy, RProperty::KMaxPropertySize+1);
+			BASIC_ERROR(r, r == KErrTooBig);
+
+			// Following defintion the property has a default value, zero-length data for byte-array and text 
+			// properties. 
+			r = prop.Define(RProperty::EByteArray, KPassPolicy, KPassPolicy);
+			BASIC_ERROR(r, r == KErrNone);
+			TBuf8<16> buf;
+			r = prop.Get(buf);
+			BASIC_ERROR(r, r == KErrNone);
+			BASIC_ERROR(buf.Size(), buf.Size() == 0);
+			r = prop.Delete();
+			BASIC_ERROR(r, r == KErrNone);
+			}
+
+		// Pending subscriptions for this property will not be completed until a new value is published.
+		TPropertySubsRequest subs(CompleteFn, this);
+		iReason = KRequestPending;
+		r = prop.Subscribe(subs);
+		r = prop.Define(type, KPassPolicy, KPassPolicy);
+		BASIC_ERROR(r, r == KErrNone);
+		BASIC_ERROR(iReason, iReason == KRequestPending);
+		r = prop.Delete();
+		BASIC_ERROR(r, r == KErrNone);
+		NKern::FSWait(&iSem);
+		BASIC_ERROR(iReason, iReason == KErrNotFound);
+
+		// If the property has not been defined Delete() fails with KErrNotFound.
+		r = prop.Delete();
+		BASIC_ERROR(r, r == KErrNotFound);
+
+		// When deleted any pending subscriptions for the property will be completed with KErrNotFound.
+		r = prop.Define(type, KPassPolicy, KPassPolicy);
+		BASIC_ERROR(r, r == KErrNone);
+		iReason = KRequestPending;
+		r = prop.Subscribe(subs);
+		BASIC_ERROR(r, r == KErrNone);
+		BASIC_ERROR(iReason, iReason == KRequestPending);
+		r = prop.Delete();
+		BASIC_ERROR(r, r == KErrNone);
+		NKern::FSWait(&iSem);
+		BASIC_ERROR(iReason, iReason == KErrNotFound);
+
+		// Any new request will not complete until the property is defined and published again.
+		iReason = KRequestPending;
+		r = prop.Subscribe(subs);
+		BASIC_ERROR(r, r == KErrNone);
+		BASIC_ERROR(iReason, iReason == KRequestPending);
+		r = prop.Define(type, KPassPolicy, KPassPolicy);
+		BASIC_ERROR(r, r == KErrNone);
+		BASIC_ERROR(iReason, iReason == KRequestPending);
+		if (type == RProperty::EInt)
+			{
+			r = prop.Set(1);
+			BASIC_ERROR(r, r == KErrNone);
+			}
+		else
+			{
+			TBuf8<16> buf((TUint8*) "Foo");
+			r = prop.Set(buf);
+			BASIC_ERROR(r, r == KErrNone);
+			}
+		NKern::FSWait(&iSem);
+		BASIC_ERROR(iReason, iReason == KErrNone);
+		r = prop.Delete();
+		BASIC_ERROR(r, r == KErrNone);
+
+		// If the property has not been defined Set()/Get() fail with KErrNotFound.
+			{
+			TInt value;
+			TBuf8<16> buf;
+			if (type == RProperty::EInt)
+				{
+				r = prop.Get(value);
+				BASIC_ERROR(r, r == KErrNotFound);
+				r = prop.Set(value);
+				BASIC_ERROR(r, r == KErrNotFound);
+				}
+			else
+				{
+				r = prop.Get(buf);
+				BASIC_ERROR(r, r == KErrNotFound);
+				r = prop.Set(buf);
+				BASIC_ERROR(r, r == KErrNotFound);
+				}
+			}
+
+		r = prop.Define(type, KPassPolicy, KPassPolicy);
+		BASIC_ERROR(r, r == KErrNone);
+
+		// If the property is larger than KMaxPropertySize Set() fails with KErrTooBig
+			{
+			if (type ==  RProperty::EByteArray)
+				{
+				TBuf8<RProperty::KMaxPropertySize + 1> buf(RProperty::KMaxPropertySize + 1);
+				r = prop.Set(buf);
+				BASIC_ERROR(r, r == KErrTooBig);
+				}
+			}
+
+		// When type of operation mismatch with the property type Set()/Get() fails with KErrArgument.
+			{
+			if (type !=  RProperty::EInt)
+				{
+				TInt value;
+				r = prop.Get(value);
+				BASIC_ERROR(r, r == KErrArgument);
+				r = prop.Set(value);
+				BASIC_ERROR(r, r == KErrArgument);
+				}
+			else
+				{
+				TBuf8<16> buf;
+				r = prop.Get(buf);
+				BASIC_ERROR(r, r == KErrArgument);
+				r = prop.Set(buf);
+				BASIC_ERROR(r, r == KErrArgument);
+				}
+			}
+
+		// Get/Set
+		if (type == RProperty::EInt)
+			{
+			r = prop.Set(1);
+			BASIC_ERROR(r, r == KErrNone);
+			TInt value = 0;
+			r = prop.Get(value);
+			BASIC_ERROR(r, r == KErrNone);
+			BASIC_ERROR(value, value == 1);
+			}
+		else 
+			{
+			TBuf8<16> ibuf((TUint8*)"Foo");
+			TBuf8<16> obuf;
+			r = prop.Set(ibuf);
+			BASIC_ERROR(r, r == KErrNone);
+			r = prop.Get(obuf);
+			BASIC_ERROR(r, r == KErrNone);
+			r = obuf.Compare(ibuf);
+			BASIC_ERROR(r, r == 0);
+			}
+
+		// If the supplied buffer is too small Get() fails with KErrOverflow and the truncated value is reported.
+		if (type == RProperty::EByteArray)
+			{
+			TBuf8<16> ibuf((TUint8*) "0123456789012345");
+			TBuf8<16> obuf((TUint8*) "abcdefghigklmnop");
+			TPtr8 optr((TUint8*) obuf.Ptr(), 0, 15);
+			r = prop.Set(ibuf);
+			BASIC_ERROR(r, r == KErrNone);
+			r = prop.Get(optr);
+			BASIC_ERROR(r, r == KErrOverflow);
+			BASIC_ERROR(optr.Length(), optr.Length() == 15); 
+			BASIC_ERROR(obuf[14], obuf[14] == '4'); 
+			BASIC_ERROR(obuf[15], obuf[15] == 'p');
+			}
+
+		// The calling thread will have the specified request status signalled when the property is next updated.
+		iReason = KRequestPending;
+		r = prop.Subscribe(subs);
+		BASIC_ERROR(r, r == KErrNone);
+		BASIC_ERROR(iReason, iReason == KRequestPending);
+		if (type == RProperty::EInt)
+			{
+			r = prop.Set(1);
+			BASIC_ERROR(r, r == KErrNone);
+			}
+		else
+			{
+			TBuf8<16> buf((TUint8*) "Foo");
+			r = prop.Set(buf);
+			BASIC_ERROR(r, r == KErrNone);
+			}
+		NKern::FSWait(&iSem);
+		BASIC_ERROR(iReason, iReason == KErrNone);
+
+		r = prop.Delete();
+		BASIC_ERROR(r, r == KErrNone);
+
+		// Cancel an outstanding subscription request.
+		// If it has not already completed, the request is completed with KErrCancelled.
+		iReason = KRequestPending;
+		r = prop.Subscribe(subs);
+		BASIC_ERROR(r, r == KErrNone);
+		BASIC_ERROR(iReason, iReason == KRequestPending);
+		prop.Cancel(subs);		
+		NKern::FSWait(&iSem);
+		BASIC_ERROR(iReason, iReason == KErrCancel);
+
+		r = prop.Define(type, KPassPolicy, KPassPolicy);
+		BASIC_ERROR(r, r == KErrNone);
+
+		iReason = KRequestPending;
+		r = prop.Subscribe(subs);
+		BASIC_ERROR(r, r == KErrNone);
+		BASIC_ERROR(iReason, iReason == KRequestPending);
+		if (type == RProperty::EInt)
+			{
+			r = prop.Set(1);
+			BASIC_ERROR(r, r == KErrNone);
+			}
+		else
+			{
+			TBuf8<16> buf((TUint8*) "Foo");
+			r = prop.Set(buf);
+			BASIC_ERROR(r, r == KErrNone);
+			}
+		NKern::FSWait(&iSem);
+		BASIC_ERROR(iReason, iReason == KErrNone);
+		prop.Cancel(subs);		
+		BASIC_ERROR(iReason, iReason == KErrNone);
+
+		iReason = KRequestPending;
+		r = prop.Subscribe(subs);
+		BASIC_ERROR(r, r == KErrNone);
+		BASIC_ERROR(iReason, iReason == KRequestPending);
+		prop.Cancel(subs);		
+		NKern::FSWait(&iSem);
+		BASIC_ERROR(iReason, iReason == KErrCancel);
+
+		r = prop.Delete();
+		BASIC_ERROR(r, r == KErrNone);
+
+		prop.Close();
+		}
+	return ETrue;
+	}
+
+//
+// Client requests.
+//
+TBool DPropLChannel::Request(TInt aFunction, TAny* a1, TAny*)
+	{
+	TBool r;
+	switch (aFunction)
+		{
+		case RPropChannel::EBasicTests:
+			RPropChannel::TBasicInfo info;
+			kumemget32(&info, a1, sizeof(info));
+			NKern::ThreadEnterCS();
+			r = Basic(&info);
+			NKern::ThreadLeaveCS();
+			break;	
+		default:
+			r = EFalse;
+			break;
+		}
+	return r;
+	}