os/kernelhwsrv/kerneltest/f32test/smassstorage/msdrive/t_msdrive.cpp
changeset 0 bde4ae8d615e
     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 +	}