diff -r 000000000000 -r a41df078684a kerneltest/e32test/property/t_prop_ldd.cpp --- /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 +#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 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; + }