1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/kernelhwsrv/kerneltest/f32test/smassstorage/msdrive/t_msdrive.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,605 @@
1.4 +// Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of the License "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +// Unit tests for the CMassStorageDrive and CDriveManager classes
1.18 +//
1.19 +//
1.20 +
1.21 +/**
1.22 + @file
1.23 + @internalTechnology
1.24 +*/
1.25 +
1.26 +#include <e32std.h>
1.27 +#include <e32std_private.h>
1.28 +#include <e32twin.h>
1.29 +#include <e32test.h>
1.30 +#include <e32property.h>
1.31 +
1.32 +#include "usbmsshared.h"
1.33 +#include "drivemanager.h"
1.34 +
1.35 +
1.36 +enum TestStep
1.37 + {
1.38 + EStepRead0,
1.39 + EStepRead1,
1.40 + EStepWrite0,
1.41 + EStepWrite1,
1.42 + EStepConnected,
1.43 + EStepActive,
1.44 + EStepMediaRemoved,
1.45 + EStepLocked,
1.46 + EStepDisconnecting,
1.47 + EStepDisconnected,
1.48 + EStepConnecting
1.49 + };
1.50 +
1.51 +LOCAL_D RTest test(_L("MSDRIVE"));
1.52 +LOCAL_D const TDriveNumber gDrive1 = EDriveL; // used drive
1.53 +LOCAL_D const TDriveNumber gDrive2 = EDriveN; // unused drive
1.54 +LOCAL_D CDriveManager* gMgr = NULL;
1.55 +LOCAL_D TestStep gTestStep = EStepRead0;
1.56 +
1.57 +#define NEXT(x) test.Next(_L(#x)); gTestStep = x;
1.58 +
1.59 +
1.60 +/**
1.61 +These CProxyDrive functions are copies of code in sf_ext.cpp,
1.62 +since we don't link to EFILE.
1.63 +*/
1.64 +CProxyDrive::CProxyDrive(CMountCB* aMount) : iMount(aMount) {}
1.65 +
1.66 +EXPORT_C TInt CProxyDrive::ControlIO(
1.67 + const RMessagePtr2& /*aMessage*/,
1.68 + TInt /*aCommand*/,TAny* /*aParam1*/,TAny* /*aParam2*/)
1.69 + {
1.70 + return(KErrNone);
1.71 + }
1.72 +
1.73 +EXPORT_C TInt CProxyDrive::DeleteNotify(TInt64 /*aPos*/, TInt /*aLength*/)
1.74 + {
1.75 + return(KErrNone);
1.76 + }
1.77 +
1.78 +EXPORT_C TInt CProxyDrive::GetInterface(TInt /*aInterfaceId*/, TAny*& /*aInterface*/, TAny* /*aInput*/)
1.79 + { return KErrNotSupported; }
1.80 +
1.81 +// Implemented the GetLastErrorInfo method here as this is usually
1.82 +// exported by EFILE, but these unit tests don't link to it.
1.83 +EXPORT_C TInt CProxyDrive::GetLastErrorInfo(TDes8& /*anErrorInfo*/)
1.84 + { return KErrNotSupported; }
1.85 +
1.86 +CProxyDrive::~CProxyDrive()
1.87 + {
1.88 + }
1.89 +
1.90 +EXPORT_C TInt CProxyDrive::Read(TInt64 aPos, TInt aLength, const TAny* aTrg, TInt /*aThreadHandle*/, TInt /*aOffset*/, TInt /*aFlags*/)
1.91 + {
1.92 + return Read(aPos, aLength, *(TDes8*)aTrg);
1.93 + }
1.94 +
1.95 +EXPORT_C TInt CProxyDrive::Write(TInt64 aPos, TInt /*aLength*/, const TAny* aSrc, TInt /*aThreadHandle*/, TInt /*aOffset*/, TInt /*aFlags*/)
1.96 + {
1.97 + return Write(aPos, *(TDesC8*)aSrc);
1.98 + }
1.99 +
1.100 +/**
1.101 +CMassStorageMountCB gets the CProxyDrive from the filesystem,
1.102 +but here we want to instantiate our own derived class for testing.
1.103 +This allows us to control the error code returned by each function.
1.104 +*/
1.105 +class CTestProxyDrive : public CProxyDrive
1.106 + {
1.107 +public:
1.108 + static TInt iRetval;
1.109 + static TInt iRetval_caps;
1.110 + static TLocalDriveCapsV4 iCaps;
1.111 +
1.112 + CTestProxyDrive(CDriveManager& aDriveManager) : CProxyDrive(NULL)
1.113 + {
1.114 + iCaps.iType = ::EMediaUnknown;
1.115 +
1.116 + iWriteTransferPublisher = CDriveWriteTransferPublisher::NewL(aDriveManager.iDrives);
1.117 + iReadTransferPublisher = CDriveReadTransferPublisher::NewL(aDriveManager.iDrives);
1.118 + }
1.119 +
1.120 + ~CTestProxyDrive()
1.121 + {
1.122 + delete iWriteTransferPublisher;
1.123 + delete iReadTransferPublisher;
1.124 + }
1.125 + virtual TInt Initialise()
1.126 + {
1.127 + return iRetval;
1.128 + }
1.129 + virtual TInt Dismounted()
1.130 + {
1.131 + return iRetval;
1.132 + }
1.133 + virtual TInt Enlarge(TInt )
1.134 + {
1.135 + return iRetval;
1.136 + }
1.137 + virtual TInt ReduceSize(TInt , TInt )
1.138 + {
1.139 + return iRetval;
1.140 + }
1.141 + virtual TInt Read(TInt64 ,TInt ,const TAny* ,TInt ,TInt )
1.142 + {
1.143 + iReadTransferPublisher->StartTimer();
1.144 + return iRetval;
1.145 + }
1.146 + virtual TInt Read(TInt64 ,TInt len, TDes8& buf)
1.147 + {
1.148 + iReadTransferPublisher->StartTimer();
1.149 + buf.SetLength(len);
1.150 + return iRetval;
1.151 + }
1.152 + virtual TInt Write(TInt64 ,TInt ,const TAny* ,TInt ,TInt )
1.153 + {
1.154 + iWriteTransferPublisher->StartTimer();
1.155 + return iRetval;
1.156 + }
1.157 + virtual TInt Write(TInt64 ,const TDesC8& )
1.158 + {
1.159 + iWriteTransferPublisher->StartTimer();
1.160 + return iRetval;
1.161 + }
1.162 + virtual TInt Caps(TDes8& aBuf)
1.163 + {
1.164 + ((TLocalDriveCapsV4Buf&)aBuf) = iCaps;
1.165 +
1.166 + return iRetval_caps;
1.167 + }
1.168 + virtual TInt Format(TFormatInfo& )
1.169 + {
1.170 + return iRetval;
1.171 + }
1.172 + virtual TInt Format(TInt64 ,TInt )
1.173 + {
1.174 + return iRetval;
1.175 + }
1.176 + virtual TInt SetMountInfo(const TDesC8* ,TInt )
1.177 + {
1.178 + return iRetval;
1.179 + }
1.180 + virtual TInt ForceRemount(TUint )
1.181 + {
1.182 + return iRetval;
1.183 + }
1.184 + virtual TInt Unlock(TMediaPassword &, TBool )
1.185 + {
1.186 + return iRetval;
1.187 + }
1.188 + virtual TInt Lock(TMediaPassword &, TMediaPassword &, TBool )
1.189 + {
1.190 + return iRetval;
1.191 + }
1.192 + virtual TInt Clear(TMediaPassword &)
1.193 + {
1.194 + return iRetval;
1.195 + }
1.196 + virtual TInt ErasePassword()
1.197 + {
1.198 + return iRetval;
1.199 + }
1.200 +
1.201 +private:
1.202 + /**
1.203 + Publish and subscribe properties for tracking data transfer volume
1.204 + */
1.205 + CDriveWriteTransferPublisher* iWriteTransferPublisher;
1.206 + CDriveReadTransferPublisher* iReadTransferPublisher;
1.207 + };
1.208 +
1.209 +TInt CTestProxyDrive::iRetval = KErrNone;
1.210 +TInt CTestProxyDrive::iRetval_caps = KErrNone;
1.211 +TLocalDriveCapsV4 CTestProxyDrive::iCaps;
1.212 +
1.213 +/**
1.214 +From USBMSAPP:
1.215 +A set of static objects that hold the latest properties published by Mass Storage,
1.216 +and a set of corresponding static functions that process the publish events.
1.217 +The functions are passed by pointer to, and invoked by, CPropertyWatch instances.
1.218 +*/
1.219 +class PropertyHandlers
1.220 + {
1.221 +public:
1.222 + /** The prototype for all public property handler functions */
1.223 + typedef void(*THandler)(RProperty&);
1.224 +
1.225 +public:
1.226 + static void Read(RProperty& aProperty);
1.227 + static void Written(RProperty& aProperty);
1.228 + static void DriveStatus(RProperty& aProperty);
1.229 +
1.230 +public:
1.231 + static TBuf8<16> iAllDrivesStatus;
1.232 + static TUsbMsBytesTransferred iKBytesRead;
1.233 + static TUsbMsBytesTransferred iKBytesWritten;
1.234 + };
1.235 +
1.236 +/**
1.237 +From USBMSAPP:
1.238 +An active object that subscribes to a specified Mass Storage property and
1.239 +calls a provided handler each time the property is published.
1.240 +*/
1.241 +class CPropertyWatch : public CActive
1.242 + {
1.243 +public:
1.244 + static CPropertyWatch* NewLC(TUsbMsDriveState_Subkey aSubkey, PropertyHandlers::THandler aHandler);
1.245 +private:
1.246 + CPropertyWatch(PropertyHandlers::THandler aHandler);
1.247 + void ConstructL(TUsbMsDriveState_Subkey aSubkey);
1.248 + ~CPropertyWatch();
1.249 + void RunL();
1.250 + void DoCancel();
1.251 +private:
1.252 + RProperty iProperty;
1.253 + PropertyHandlers::THandler iHandler;
1.254 + };
1.255 +
1.256 +CPropertyWatch* CPropertyWatch::NewLC(TUsbMsDriveState_Subkey aSubkey, PropertyHandlers::THandler aHandler)
1.257 + {
1.258 + CPropertyWatch* me=new(ELeave) CPropertyWatch(aHandler);
1.259 + CleanupStack::PushL(me);
1.260 + me->ConstructL(aSubkey);
1.261 + return me;
1.262 + }
1.263 +
1.264 +CPropertyWatch::CPropertyWatch(PropertyHandlers::THandler aHandler)
1.265 + : CActive(0), iHandler(aHandler)
1.266 + {}
1.267 +
1.268 +void CPropertyWatch::ConstructL(TUsbMsDriveState_Subkey aSubkey)
1.269 + {
1.270 + User::LeaveIfError(iProperty.Attach(KUsbMsDriveState_Category, aSubkey));
1.271 + CActiveScheduler::Add(this);
1.272 + // initial subscription and process current property value
1.273 + RunL();
1.274 + }
1.275 +
1.276 +CPropertyWatch::~CPropertyWatch()
1.277 + {
1.278 + Cancel();
1.279 + iProperty.Close();
1.280 + }
1.281 +
1.282 +void CPropertyWatch::DoCancel()
1.283 + {
1.284 + iProperty.Cancel();
1.285 + }
1.286 +
1.287 +void CPropertyWatch::RunL()
1.288 + {
1.289 + // resubscribe before processing new value to prevent missing updates
1.290 + iProperty.Subscribe(iStatus);
1.291 +
1.292 + iHandler(iProperty);
1.293 +
1.294 + SetActive();
1.295 + }
1.296 +
1.297 +
1.298 +TBuf8<16> PropertyHandlers::iAllDrivesStatus;
1.299 +TUsbMsBytesTransferred PropertyHandlers::iKBytesRead;
1.300 +TUsbMsBytesTransferred PropertyHandlers::iKBytesWritten;
1.301 +
1.302 +
1.303 +/**
1.304 +Handle a publish event for the Bytes Read property.
1.305 +*/
1.306 +void PropertyHandlers::Read(RProperty& aProperty)
1.307 + {
1.308 + const TUint KNoBytesToRead = 1000;
1.309 + test(aProperty.Get(iKBytesRead)==KErrNone);
1.310 + TInt kbytes = iKBytesRead[0];
1.311 +
1.312 + TBuf8<KNoBytesToRead> buf;
1.313 + buf.SetLength(KNoBytesToRead);
1.314 + TInt err;
1.315 +
1.316 + switch(gTestStep)
1.317 + {
1.318 + case EStepRead0:
1.319 + // don't do anything until 1st KB reported in 1s interval
1.320 + if(kbytes==0)
1.321 + {
1.322 + break;
1.323 + }
1.324 + test(kbytes==1);
1.325 +
1.326 + test(KErrNone == gMgr->Drive(0,err)->Read(0,KNoBytesToRead,buf));
1.327 + NEXT(EStepRead1);
1.328 + break;
1.329 +
1.330 + case EStepRead1:
1.331 + test(kbytes==2);
1.332 +
1.333 + // trigger an update:
1.334 + test(KErrNone == gMgr->Drive(0,err)->Write(0,buf));
1.335 + NEXT(EStepWrite0);
1.336 + break;
1.337 +
1.338 + default:
1.339 + break;
1.340 + }
1.341 + }
1.342 +
1.343 +/**
1.344 +Handle a publish event for the Bytes Written property.
1.345 +*/
1.346 +void PropertyHandlers::Written(RProperty& aProperty)
1.347 + {
1.348 + const TUint KNoBytesToWrite = 1000;
1.349 + test(aProperty.Get(iKBytesWritten)==KErrNone);
1.350 + TInt kbytes = iKBytesWritten[0];
1.351 +
1.352 + TBuf8<KNoBytesToWrite> buf;
1.353 + buf.SetLength(KNoBytesToWrite);
1.354 + TInt err;
1.355 +
1.356 + switch(gTestStep)
1.357 + {
1.358 + case EStepWrite0:
1.359 + test(kbytes==2);
1.360 +
1.361 + test(KErrNone == gMgr->Drive(0,err)->Write(0,buf));
1.362 + NEXT(EStepWrite1);
1.363 + break;
1.364 +
1.365 + case EStepWrite1:
1.366 + test(kbytes==3);
1.367 +
1.368 + // trigger transient change to Active state:
1.369 + test(KErrNone == gMgr->Drive(0,err)->Write(0,buf));
1.370 + NEXT(EStepConnected);
1.371 + break;
1.372 +
1.373 + default:
1.374 + break;
1.375 + }
1.376 + }
1.377 +
1.378 +/**
1.379 +Handle a publish event for the Drive Status property.
1.380 +*/
1.381 +void PropertyHandlers::DriveStatus(RProperty& aProperty)
1.382 + {
1.383 + RDebug::Print(_L(">> PropertyHandlers::DriveStatus"));
1.384 + TInt err = aProperty.Get(iAllDrivesStatus);
1.385 + test(err == KErrNone);
1.386 +
1.387 + // There should be status for 2 drives:
1.388 + // (Note: there is a pair of bytes per drive,
1.389 + // drive number and drive status.)
1.390 + test(2 == iAllDrivesStatus.Length()/2);
1.391 + test(iAllDrivesStatus[0] == gDrive1);
1.392 + test(iAllDrivesStatus[2*1] == gDrive2);
1.393 + TInt status = iAllDrivesStatus[1];
1.394 +
1.395 + switch(gTestStep)
1.396 + {
1.397 + case EStepConnected:
1.398 + test(status==EUsbMsDriveState_Connected);
1.399 +
1.400 + test(KErrNone==gMgr->Drive(0,err)->SetCritical(ETrue));
1.401 + NEXT(EStepActive);
1.402 + break;
1.403 +
1.404 + case EStepActive:
1.405 + test(status==EUsbMsDriveState_Active);
1.406 +
1.407 + CTestProxyDrive::iRetval_caps = KErrNotReady;
1.408 + test(CMassStorageDrive::EMediaNotPresent
1.409 + ==gMgr->Drive(0,err)->CheckDriveState());
1.410 + CTestProxyDrive::iRetval_caps = KErrNone;
1.411 +
1.412 + NEXT(EStepMediaRemoved);
1.413 + break;
1.414 +
1.415 + case EStepMediaRemoved:
1.416 + {
1.417 + test(status==EUsbMsDriveState_MediaNotPresent);
1.418 +
1.419 + gMgr->Drive(0,err)->CheckDriveState(); // clear old state
1.420 +
1.421 + CTestProxyDrive::iRetval = KErrLocked;
1.422 + TBuf8<1> buf;
1.423 + buf.SetLength(1);
1.424 + test(KErrLocked==gMgr->Drive(0,err)->Write(0,buf));
1.425 + CTestProxyDrive::iRetval = KErrNone;
1.426 + NEXT(EStepLocked);
1.427 + }
1.428 + break;
1.429 +
1.430 + case EStepLocked:
1.431 + test(status==EUsbMsDriveState_Locked);
1.432 +
1.433 + test(KErrNone == gMgr->Disconnect(0));
1.434 + test(KErrNone == gMgr->Disconnect(0)); // ensure it can be called more than once
1.435 + NEXT(EStepDisconnecting);
1.436 + break;
1.437 +
1.438 + case EStepDisconnecting:
1.439 + test(status==EUsbMsDriveState_Disconnecting);
1.440 +
1.441 + test(KErrNone == gMgr->DeregisterDrive(0));
1.442 + NEXT(EStepDisconnected);
1.443 + break;
1.444 +
1.445 + case EStepDisconnected:
1.446 + test(status==EUsbMsDriveState_Disconnected);
1.447 +
1.448 + test(KErrNone == gMgr->Connect(0));
1.449 + test(KErrNone == gMgr->Connect(0)); // ensure it can be called more than once
1.450 + NEXT(EStepConnecting);
1.451 + break;
1.452 +
1.453 + case EStepConnecting:
1.454 + test(status==EUsbMsDriveState_Connecting);
1.455 + CActiveScheduler::Stop();
1.456 + break;
1.457 +
1.458 + default:
1.459 + break;
1.460 + }
1.461 +
1.462 + RDebug::Print(_L("<< PropertyHandlers::DriveStatus"));
1.463 + }
1.464 +
1.465 +LOCAL_C void doTestL()
1.466 + {
1.467 + test.Start(_L("MSDrive1"));
1.468 +
1.469 + CActiveScheduler* sched = new(ELeave) CActiveScheduler;
1.470 + CleanupStack::PushL(sched);
1.471 + CActiveScheduler::Install(sched);
1.472 +
1.473 + RArray<TInt> driveMap;
1.474 + CleanupClosePushL(driveMap);
1.475 + driveMap.AppendL(gDrive1);
1.476 + driveMap.AppendL(gDrive2);
1.477 +
1.478 + gMgr = CDriveManager::NewL(driveMap);
1.479 + CleanupStack::PushL(gMgr);
1.480 + TInt err = KErrGeneral;
1.481 + CMassStorageDrive* drive1 = gMgr->Drive(0,err);
1.482 + test(err == KErrNone);
1.483 +
1.484 + ///////////////////////////////////////////////////////////////////////////
1.485 + test.Next(_L("Check initial state"));
1.486 + test(CMassStorageDrive::EDisconnected==drive1->MountState());
1.487 + test(CMassStorageDrive::EErrDisMounted==drive1->DriveState());
1.488 + test(0==drive1->KBytesRead());
1.489 + test(0==drive1->KBytesWritten());
1.490 + test(EFalse==drive1->IsMediaChanged());
1.491 +
1.492 + ///////////////////////////////////////////////////////////////////////////
1.493 + test.Next(_L("Ensure Read/Write/Caps don't work when disconnected"));
1.494 +
1.495 + const TInt KNoBytes = 1000;
1.496 + TBuf8<KNoBytes> buf;
1.497 + TLocalDriveCapsV4 caps;
1.498 + test(KErrDisconnected==drive1->Read(0,0,buf));
1.499 + test(KErrDisconnected==drive1->Write(0,buf));
1.500 + test(KErrDisconnected==drive1->Caps(caps));
1.501 +
1.502 + ///////////////////////////////////////////////////////////////////////////
1.503 + test.Next(_L("Test EConnecting state"));
1.504 +
1.505 + drive1->SetMountConnecting();
1.506 + test(CMassStorageDrive::EConnecting==drive1->MountState());
1.507 + test(KErrDisconnected==drive1->Read(0,0,buf));
1.508 + test(KErrDisconnected==drive1->Write(0,buf));
1.509 + test(KErrDisconnected==drive1->Caps(caps));
1.510 +
1.511 + ///////////////////////////////////////////////////////////////////////////
1.512 + test.Next(_L("Test EDisconnecting state"));
1.513 +
1.514 + drive1->SetMountDisconnecting();
1.515 + test(CMassStorageDrive::EDisconnecting==drive1->MountState());
1.516 + test(KErrDisconnected==drive1->Read(0,0,buf));
1.517 + test(KErrDisconnected==drive1->Write(0,buf));
1.518 + test(KErrDisconnected==drive1->Caps(caps));
1.519 +
1.520 + ///////////////////////////////////////////////////////////////////////////
1.521 + test.Next(_L("Test EConnected state"));
1.522 +
1.523 + CTestProxyDrive* proxyDrive = new(ELeave) CTestProxyDrive(*gMgr);
1.524 + CleanupStack::PushL(proxyDrive);
1.525 +
1.526 + TBool mediaChanged = EFalse;
1.527 + test(KErrNone==gMgr->RegisterDrive(*proxyDrive, mediaChanged, 0));
1.528 + test(CMassStorageDrive::EConnected==drive1->MountState());
1.529 +
1.530 + ///////////////////////////////////////////////////////////////////////////
1.531 + test.Next(_L("Test SetCritical"));
1.532 + test(CMassStorageDrive::EIdle==drive1->DriveState());
1.533 + test(KErrNone==drive1->SetCritical(ETrue));
1.534 + test(CMassStorageDrive::EActive==drive1->DriveState());
1.535 + test(KErrNone==drive1->SetCritical(EFalse));
1.536 + test(CMassStorageDrive::EIdle==drive1->DriveState());
1.537 +
1.538 + ///////////////////////////////////////////////////////////////////////////
1.539 + test.Next(_L("Test that ProxyDrive is called"));
1.540 +
1.541 + CTestProxyDrive::iRetval = KErrNone;
1.542 +
1.543 + // Test that bytesRead is incremented correctly
1.544 + // when the count increments from 999 to 1000:
1.545 + test(KErrNone==drive1->Read(0,999,buf));
1.546 + test(0==drive1->KBytesRead());
1.547 + test(KErrNone==drive1->Read(0,1,buf));
1.548 + test(1==drive1->KBytesRead());
1.549 +
1.550 + buf.SetLength(KNoBytes);
1.551 + test(KErrNone==drive1->Write(0,buf));
1.552 + test(KErrNone==drive1->Caps(caps));
1.553 + // Write was called when EIdle, should restore state to EIdle
1.554 + // after transient EActive state.
1.555 + test(CMassStorageDrive::EIdle==drive1->DriveState());
1.556 +
1.557 + CTestProxyDrive::iRetval = KErrDied; // arbitrary test value
1.558 + CTestProxyDrive::iRetval_caps = KErrDied;
1.559 + test(KErrDied==drive1->Read(0,0,buf));
1.560 + test(KErrDied==drive1->Write(0,buf));
1.561 + test(KErrDied==drive1->Caps(caps));
1.562 + CTestProxyDrive::iRetval = KErrNone;
1.563 + CTestProxyDrive::iRetval_caps = KErrNone;
1.564 +
1.565 + test.Next(_L("Test IsMediaChanged"));
1.566 + test(EFalse==drive1->IsMediaChanged(ETrue));
1.567 + test(EFalse==drive1->IsMediaChanged(EFalse));
1.568 +
1.569 + ///////////////////////////////////////////////////////////////////////////
1.570 +
1.571 + CPropertyWatch::NewLC(EUsbMsDriveState_KBytesRead, PropertyHandlers::Read);
1.572 + CPropertyWatch::NewLC(EUsbMsDriveState_KBytesWritten, PropertyHandlers::Written);
1.573 + CPropertyWatch::NewLC(EUsbMsDriveState_DriveStatus, PropertyHandlers::DriveStatus);
1.574 +
1.575 + ///////////////////////////////////////////////////////////////////////////
1.576 +
1.577 + NEXT(EStepRead0);
1.578 + CActiveScheduler::Start();
1.579 +
1.580 + ///////////////////////////////////////////////////////////////////////////
1.581 +
1.582 + test.Printf(_L("\nCLEANING UP\n"));
1.583 +
1.584 + CleanupStack::PopAndDestroy(3); //CPropertyWatch x 3
1.585 + CleanupStack::PopAndDestroy(proxyDrive);
1.586 + CleanupStack::PopAndDestroy(gMgr);
1.587 + CleanupStack::PopAndDestroy(&driveMap);
1.588 + CleanupStack::PopAndDestroy(sched);
1.589 +
1.590 + return;
1.591 + }
1.592 +
1.593 +GLDEF_C TInt E32Main()
1.594 + {
1.595 + __UHEAP_MARK;
1.596 + CTrapCleanup* cleanup=CTrapCleanup::New();
1.597 +
1.598 + TRAPD(error,doTestL());
1.599 + if (error)
1.600 + test.Printf(_L("Leave occurred; code=%d\n"), error);
1.601 +
1.602 + test.End(); // output success/fail
1.603 + test.Close();
1.604 +
1.605 + delete cleanup;
1.606 + __UHEAP_MARKEND;
1.607 + return 0;
1.608 + }