os/kernelhwsrv/kerneltest/f32test/smassstorage/msdrive/t_msdrive.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
// Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     2
// All rights reserved.
sl@0
     3
// This component and the accompanying materials are made available
sl@0
     4
// under the terms of the License "Eclipse Public License v1.0"
sl@0
     5
// which accompanies this distribution, and is available
sl@0
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     7
//
sl@0
     8
// Initial Contributors:
sl@0
     9
// Nokia Corporation - initial contribution.
sl@0
    10
//
sl@0
    11
// Contributors:
sl@0
    12
//
sl@0
    13
// Description:
sl@0
    14
// Unit tests for the CMassStorageDrive and CDriveManager classes
sl@0
    15
// 
sl@0
    16
//
sl@0
    17
sl@0
    18
/**
sl@0
    19
 @file
sl@0
    20
 @internalTechnology
sl@0
    21
*/
sl@0
    22
sl@0
    23
#include <e32std.h>
sl@0
    24
#include <e32std_private.h>
sl@0
    25
#include <e32twin.h>
sl@0
    26
#include <e32test.h>
sl@0
    27
#include <e32property.h>
sl@0
    28
sl@0
    29
#include "usbmsshared.h"
sl@0
    30
#include "drivemanager.h"
sl@0
    31
sl@0
    32
sl@0
    33
enum TestStep
sl@0
    34
	{
sl@0
    35
	EStepRead0,
sl@0
    36
	EStepRead1,
sl@0
    37
	EStepWrite0,
sl@0
    38
	EStepWrite1,
sl@0
    39
	EStepConnected,
sl@0
    40
	EStepActive,
sl@0
    41
	EStepMediaRemoved,
sl@0
    42
	EStepLocked,
sl@0
    43
	EStepDisconnecting,
sl@0
    44
	EStepDisconnected,
sl@0
    45
	EStepConnecting
sl@0
    46
	};
sl@0
    47
sl@0
    48
LOCAL_D RTest test(_L("MSDRIVE"));
sl@0
    49
LOCAL_D const TDriveNumber gDrive1 = EDriveL; // used drive
sl@0
    50
LOCAL_D const TDriveNumber gDrive2 = EDriveN; // unused drive
sl@0
    51
LOCAL_D CDriveManager* gMgr = NULL;
sl@0
    52
LOCAL_D TestStep gTestStep = EStepRead0;
sl@0
    53
sl@0
    54
#define NEXT(x) test.Next(_L(#x)); gTestStep = x;
sl@0
    55
sl@0
    56
sl@0
    57
/**
sl@0
    58
These CProxyDrive functions are copies of code in sf_ext.cpp, 
sl@0
    59
since we don't link to EFILE.
sl@0
    60
*/
sl@0
    61
CProxyDrive::CProxyDrive(CMountCB* aMount) : iMount(aMount) {}
sl@0
    62
sl@0
    63
EXPORT_C TInt CProxyDrive::ControlIO(
sl@0
    64
		const RMessagePtr2& /*aMessage*/,
sl@0
    65
		TInt /*aCommand*/,TAny* /*aParam1*/,TAny* /*aParam2*/)
sl@0
    66
	{
sl@0
    67
	return(KErrNone);
sl@0
    68
	}
sl@0
    69
sl@0
    70
EXPORT_C TInt CProxyDrive::DeleteNotify(TInt64 /*aPos*/, TInt /*aLength*/)
sl@0
    71
	{
sl@0
    72
	return(KErrNone);
sl@0
    73
	}
sl@0
    74
sl@0
    75
EXPORT_C TInt CProxyDrive::GetInterface(TInt /*aInterfaceId*/, TAny*& /*aInterface*/, TAny* /*aInput*/)
sl@0
    76
	{ return KErrNotSupported; }
sl@0
    77
sl@0
    78
// Implemented the GetLastErrorInfo method here as this is usually 
sl@0
    79
// exported by EFILE, but these unit tests don't link to it.
sl@0
    80
EXPORT_C TInt CProxyDrive::GetLastErrorInfo(TDes8& /*anErrorInfo*/)
sl@0
    81
	{ return KErrNotSupported; }
sl@0
    82
sl@0
    83
CProxyDrive::~CProxyDrive()
sl@0
    84
	{
sl@0
    85
	}
sl@0
    86
sl@0
    87
EXPORT_C TInt CProxyDrive::Read(TInt64 aPos, TInt aLength, const TAny* aTrg, TInt /*aThreadHandle*/, TInt /*aOffset*/, TInt /*aFlags*/)
sl@0
    88
	{
sl@0
    89
	return Read(aPos, aLength, *(TDes8*)aTrg);
sl@0
    90
	}
sl@0
    91
sl@0
    92
EXPORT_C TInt CProxyDrive::Write(TInt64 aPos, TInt /*aLength*/, const TAny* aSrc, TInt /*aThreadHandle*/, TInt /*aOffset*/, TInt /*aFlags*/)
sl@0
    93
	{
sl@0
    94
	return Write(aPos, *(TDesC8*)aSrc);
sl@0
    95
	}
sl@0
    96
sl@0
    97
/** 
sl@0
    98
CMassStorageMountCB gets the CProxyDrive from the filesystem,
sl@0
    99
but here we want to instantiate our own derived class for testing.
sl@0
   100
This allows us to control the error code returned by each function.
sl@0
   101
*/
sl@0
   102
class CTestProxyDrive : public CProxyDrive
sl@0
   103
	{
sl@0
   104
public:
sl@0
   105
	static TInt iRetval;
sl@0
   106
	static TInt iRetval_caps;
sl@0
   107
	static TLocalDriveCapsV4 iCaps;
sl@0
   108
		 
sl@0
   109
	CTestProxyDrive(CDriveManager& aDriveManager) : CProxyDrive(NULL)
sl@0
   110
		{
sl@0
   111
		iCaps.iType = ::EMediaUnknown;
sl@0
   112
sl@0
   113
		iWriteTransferPublisher = CDriveWriteTransferPublisher::NewL(aDriveManager.iDrives);
sl@0
   114
		iReadTransferPublisher = CDriveReadTransferPublisher::NewL(aDriveManager.iDrives);
sl@0
   115
		}
sl@0
   116
		
sl@0
   117
	~CTestProxyDrive() 
sl@0
   118
		{
sl@0
   119
		delete iWriteTransferPublisher;
sl@0
   120
		delete iReadTransferPublisher;
sl@0
   121
		}
sl@0
   122
	virtual TInt Initialise()
sl@0
   123
		{
sl@0
   124
		return iRetval;
sl@0
   125
		}
sl@0
   126
	virtual TInt Dismounted()
sl@0
   127
		{
sl@0
   128
		return iRetval;
sl@0
   129
		}
sl@0
   130
	virtual TInt Enlarge(TInt )
sl@0
   131
		{
sl@0
   132
		return iRetval;
sl@0
   133
		}
sl@0
   134
	virtual TInt ReduceSize(TInt , TInt )
sl@0
   135
		{
sl@0
   136
		return iRetval;
sl@0
   137
		}
sl@0
   138
	virtual TInt Read(TInt64 ,TInt ,const TAny* ,TInt ,TInt )
sl@0
   139
		{
sl@0
   140
		iReadTransferPublisher->StartTimer();
sl@0
   141
		return iRetval;
sl@0
   142
		}
sl@0
   143
	virtual TInt Read(TInt64 ,TInt len, TDes8& buf)
sl@0
   144
		{
sl@0
   145
		iReadTransferPublisher->StartTimer();
sl@0
   146
		buf.SetLength(len);
sl@0
   147
		return iRetval;
sl@0
   148
		}
sl@0
   149
	virtual TInt Write(TInt64 ,TInt ,const TAny* ,TInt ,TInt )
sl@0
   150
		{
sl@0
   151
		iWriteTransferPublisher->StartTimer();
sl@0
   152
		return iRetval;
sl@0
   153
		}
sl@0
   154
	virtual TInt Write(TInt64 ,const TDesC8& )
sl@0
   155
		{
sl@0
   156
		iWriteTransferPublisher->StartTimer();
sl@0
   157
		return iRetval;
sl@0
   158
		}
sl@0
   159
	virtual TInt Caps(TDes8& aBuf)
sl@0
   160
		{
sl@0
   161
		((TLocalDriveCapsV4Buf&)aBuf) = iCaps;
sl@0
   162
		
sl@0
   163
		return iRetval_caps;
sl@0
   164
		}
sl@0
   165
	virtual TInt Format(TFormatInfo& )
sl@0
   166
		{
sl@0
   167
		return iRetval;
sl@0
   168
		}
sl@0
   169
	virtual TInt Format(TInt64 ,TInt )
sl@0
   170
		{
sl@0
   171
		return iRetval;
sl@0
   172
		}
sl@0
   173
	virtual TInt SetMountInfo(const TDesC8* ,TInt )
sl@0
   174
		{
sl@0
   175
		return iRetval;
sl@0
   176
		}
sl@0
   177
	virtual TInt ForceRemount(TUint )
sl@0
   178
		{
sl@0
   179
		return iRetval;
sl@0
   180
		}
sl@0
   181
	virtual TInt Unlock(TMediaPassword &, TBool )
sl@0
   182
		{
sl@0
   183
		return iRetval;
sl@0
   184
		}
sl@0
   185
	virtual TInt Lock(TMediaPassword &, TMediaPassword &, TBool )
sl@0
   186
		{
sl@0
   187
		return iRetval;
sl@0
   188
		}
sl@0
   189
	virtual TInt Clear(TMediaPassword &)
sl@0
   190
		{
sl@0
   191
		return iRetval;
sl@0
   192
		}
sl@0
   193
	virtual TInt ErasePassword()
sl@0
   194
		{
sl@0
   195
		return iRetval;
sl@0
   196
		}
sl@0
   197
sl@0
   198
private:
sl@0
   199
	/**
sl@0
   200
	Publish and subscribe properties for tracking data transfer volume
sl@0
   201
	*/
sl@0
   202
	CDriveWriteTransferPublisher* iWriteTransferPublisher;
sl@0
   203
	CDriveReadTransferPublisher* iReadTransferPublisher;
sl@0
   204
	};
sl@0
   205
	
sl@0
   206
TInt CTestProxyDrive::iRetval = KErrNone;
sl@0
   207
TInt CTestProxyDrive::iRetval_caps = KErrNone;
sl@0
   208
TLocalDriveCapsV4 CTestProxyDrive::iCaps;
sl@0
   209
sl@0
   210
/**
sl@0
   211
From USBMSAPP:
sl@0
   212
A set of static objects that hold the latest properties published by Mass Storage,
sl@0
   213
and a set of corresponding static functions that process the publish events. 
sl@0
   214
The functions are passed by pointer to, and invoked by, CPropertyWatch instances.
sl@0
   215
*/
sl@0
   216
class PropertyHandlers
sl@0
   217
	{
sl@0
   218
public:
sl@0
   219
	/** The prototype for all public property handler functions */
sl@0
   220
	typedef void(*THandler)(RProperty&);
sl@0
   221
sl@0
   222
public:
sl@0
   223
	static void Read(RProperty& aProperty);
sl@0
   224
	static void Written(RProperty& aProperty);
sl@0
   225
	static void DriveStatus(RProperty& aProperty);
sl@0
   226
sl@0
   227
public:
sl@0
   228
	static TBuf8<16> iAllDrivesStatus;
sl@0
   229
	static TUsbMsBytesTransferred iKBytesRead;
sl@0
   230
	static TUsbMsBytesTransferred iKBytesWritten;
sl@0
   231
	};
sl@0
   232
sl@0
   233
/**
sl@0
   234
From USBMSAPP:
sl@0
   235
An active object that subscribes to a specified Mass Storage property and
sl@0
   236
calls a provided handler each time the property is published.
sl@0
   237
*/
sl@0
   238
class CPropertyWatch : public CActive
sl@0
   239
	{
sl@0
   240
public:
sl@0
   241
	static CPropertyWatch* NewLC(TUsbMsDriveState_Subkey aSubkey, PropertyHandlers::THandler aHandler);
sl@0
   242
private:
sl@0
   243
	CPropertyWatch(PropertyHandlers::THandler aHandler);
sl@0
   244
	void ConstructL(TUsbMsDriveState_Subkey aSubkey);
sl@0
   245
	~CPropertyWatch();
sl@0
   246
	void RunL();
sl@0
   247
	void DoCancel();
sl@0
   248
private:
sl@0
   249
	RProperty iProperty;
sl@0
   250
	PropertyHandlers::THandler iHandler;
sl@0
   251
	};
sl@0
   252
sl@0
   253
CPropertyWatch* CPropertyWatch::NewLC(TUsbMsDriveState_Subkey aSubkey, PropertyHandlers::THandler aHandler)
sl@0
   254
	{
sl@0
   255
	CPropertyWatch* me=new(ELeave) CPropertyWatch(aHandler);
sl@0
   256
	CleanupStack::PushL(me);
sl@0
   257
	me->ConstructL(aSubkey);
sl@0
   258
	return me;
sl@0
   259
	}
sl@0
   260
sl@0
   261
CPropertyWatch::CPropertyWatch(PropertyHandlers::THandler aHandler)
sl@0
   262
	: CActive(0), iHandler(aHandler)
sl@0
   263
	{}
sl@0
   264
sl@0
   265
void CPropertyWatch::ConstructL(TUsbMsDriveState_Subkey aSubkey)
sl@0
   266
	{
sl@0
   267
	User::LeaveIfError(iProperty.Attach(KUsbMsDriveState_Category, aSubkey));
sl@0
   268
	CActiveScheduler::Add(this);
sl@0
   269
	// initial subscription and process current property value
sl@0
   270
	RunL();
sl@0
   271
	}
sl@0
   272
sl@0
   273
CPropertyWatch::~CPropertyWatch()
sl@0
   274
	{
sl@0
   275
	Cancel();
sl@0
   276
	iProperty.Close();
sl@0
   277
	}
sl@0
   278
sl@0
   279
void CPropertyWatch::DoCancel()
sl@0
   280
	{
sl@0
   281
	iProperty.Cancel();
sl@0
   282
	}
sl@0
   283
sl@0
   284
void CPropertyWatch::RunL()
sl@0
   285
	{
sl@0
   286
	// resubscribe before processing new value to prevent missing updates
sl@0
   287
	iProperty.Subscribe(iStatus);
sl@0
   288
sl@0
   289
	iHandler(iProperty);
sl@0
   290
sl@0
   291
	SetActive();
sl@0
   292
	}
sl@0
   293
sl@0
   294
sl@0
   295
TBuf8<16> PropertyHandlers::iAllDrivesStatus;
sl@0
   296
TUsbMsBytesTransferred PropertyHandlers::iKBytesRead;
sl@0
   297
TUsbMsBytesTransferred PropertyHandlers::iKBytesWritten;
sl@0
   298
sl@0
   299
sl@0
   300
/** 
sl@0
   301
Handle a publish event for the Bytes Read property.
sl@0
   302
*/
sl@0
   303
void PropertyHandlers::Read(RProperty& aProperty)
sl@0
   304
	{
sl@0
   305
	const TUint KNoBytesToRead = 1000;
sl@0
   306
	test(aProperty.Get(iKBytesRead)==KErrNone);
sl@0
   307
	TInt kbytes = iKBytesRead[0];
sl@0
   308
sl@0
   309
	TBuf8<KNoBytesToRead> buf;
sl@0
   310
	buf.SetLength(KNoBytesToRead);
sl@0
   311
	TInt err;
sl@0
   312
sl@0
   313
	switch(gTestStep)
sl@0
   314
		{
sl@0
   315
		case EStepRead0:
sl@0
   316
			// don't do anything until 1st KB reported in 1s interval
sl@0
   317
			if(kbytes==0)
sl@0
   318
				{
sl@0
   319
				break;
sl@0
   320
				}
sl@0
   321
			test(kbytes==1);
sl@0
   322
sl@0
   323
			test(KErrNone == gMgr->Drive(0,err)->Read(0,KNoBytesToRead,buf));
sl@0
   324
			NEXT(EStepRead1);
sl@0
   325
			break;
sl@0
   326
sl@0
   327
		case EStepRead1:
sl@0
   328
			test(kbytes==2);
sl@0
   329
			
sl@0
   330
			// trigger an update:
sl@0
   331
			test(KErrNone == gMgr->Drive(0,err)->Write(0,buf));
sl@0
   332
			NEXT(EStepWrite0);
sl@0
   333
			break;
sl@0
   334
			
sl@0
   335
		default:
sl@0
   336
			break;
sl@0
   337
		}
sl@0
   338
	}
sl@0
   339
sl@0
   340
/** 
sl@0
   341
Handle a publish event for the Bytes Written property.
sl@0
   342
*/
sl@0
   343
void PropertyHandlers::Written(RProperty& aProperty)
sl@0
   344
	{
sl@0
   345
	const TUint KNoBytesToWrite = 1000;
sl@0
   346
	test(aProperty.Get(iKBytesWritten)==KErrNone);
sl@0
   347
	TInt kbytes = iKBytesWritten[0];
sl@0
   348
sl@0
   349
	TBuf8<KNoBytesToWrite> buf;
sl@0
   350
	buf.SetLength(KNoBytesToWrite);
sl@0
   351
	TInt err;
sl@0
   352
sl@0
   353
	switch(gTestStep)
sl@0
   354
		{
sl@0
   355
		case EStepWrite0:
sl@0
   356
			test(kbytes==2);
sl@0
   357
sl@0
   358
			test(KErrNone == gMgr->Drive(0,err)->Write(0,buf));
sl@0
   359
			NEXT(EStepWrite1);
sl@0
   360
			break;
sl@0
   361
sl@0
   362
		case EStepWrite1:
sl@0
   363
			test(kbytes==3);
sl@0
   364
			
sl@0
   365
			// trigger transient change to Active state:
sl@0
   366
			test(KErrNone == gMgr->Drive(0,err)->Write(0,buf));
sl@0
   367
			NEXT(EStepConnected);
sl@0
   368
			break;
sl@0
   369
sl@0
   370
		default:
sl@0
   371
			break;
sl@0
   372
		}
sl@0
   373
	}
sl@0
   374
sl@0
   375
/** 
sl@0
   376
Handle a publish event for the Drive Status property.
sl@0
   377
*/
sl@0
   378
void PropertyHandlers::DriveStatus(RProperty& aProperty)
sl@0
   379
	{
sl@0
   380
	RDebug::Print(_L(">> PropertyHandlers::DriveStatus")); 
sl@0
   381
	TInt err = aProperty.Get(iAllDrivesStatus);
sl@0
   382
	test(err == KErrNone);
sl@0
   383
sl@0
   384
	// There should be status for 2 drives:
sl@0
   385
	// (Note: there is a pair of bytes per drive,
sl@0
   386
	// drive number and drive status.)
sl@0
   387
	test(2 == iAllDrivesStatus.Length()/2);
sl@0
   388
	test(iAllDrivesStatus[0] == gDrive1);
sl@0
   389
	test(iAllDrivesStatus[2*1] == gDrive2);
sl@0
   390
	TInt status = iAllDrivesStatus[1];
sl@0
   391
sl@0
   392
	switch(gTestStep)
sl@0
   393
		{
sl@0
   394
		case EStepConnected:
sl@0
   395
			test(status==EUsbMsDriveState_Connected);
sl@0
   396
			
sl@0
   397
			test(KErrNone==gMgr->Drive(0,err)->SetCritical(ETrue));	
sl@0
   398
			NEXT(EStepActive);
sl@0
   399
			break;
sl@0
   400
			
sl@0
   401
		case EStepActive:
sl@0
   402
			test(status==EUsbMsDriveState_Active);
sl@0
   403
					
sl@0
   404
			CTestProxyDrive::iRetval_caps = KErrNotReady;
sl@0
   405
			test(CMassStorageDrive::EMediaNotPresent
sl@0
   406
					==gMgr->Drive(0,err)->CheckDriveState());	
sl@0
   407
			CTestProxyDrive::iRetval_caps = KErrNone;
sl@0
   408
			
sl@0
   409
			NEXT(EStepMediaRemoved);
sl@0
   410
			break;
sl@0
   411
			
sl@0
   412
		case EStepMediaRemoved:
sl@0
   413
			{
sl@0
   414
			test(status==EUsbMsDriveState_MediaNotPresent);
sl@0
   415
			
sl@0
   416
			gMgr->Drive(0,err)->CheckDriveState(); // clear old state
sl@0
   417
			
sl@0
   418
			CTestProxyDrive::iRetval = KErrLocked;
sl@0
   419
			TBuf8<1> buf;
sl@0
   420
			buf.SetLength(1);
sl@0
   421
			test(KErrLocked==gMgr->Drive(0,err)->Write(0,buf));	
sl@0
   422
			CTestProxyDrive::iRetval = KErrNone;
sl@0
   423
			NEXT(EStepLocked);
sl@0
   424
			}
sl@0
   425
			break;
sl@0
   426
			
sl@0
   427
		case EStepLocked:
sl@0
   428
			test(status==EUsbMsDriveState_Locked);
sl@0
   429
			
sl@0
   430
			test(KErrNone == gMgr->Disconnect(0));
sl@0
   431
			test(KErrNone == gMgr->Disconnect(0)); // ensure it can be called more than once
sl@0
   432
			NEXT(EStepDisconnecting);
sl@0
   433
			break;
sl@0
   434
		
sl@0
   435
		case EStepDisconnecting:
sl@0
   436
			test(status==EUsbMsDriveState_Disconnecting);
sl@0
   437
			
sl@0
   438
			test(KErrNone == gMgr->DeregisterDrive(0));
sl@0
   439
			NEXT(EStepDisconnected);
sl@0
   440
			break;
sl@0
   441
		
sl@0
   442
		case EStepDisconnected:
sl@0
   443
			test(status==EUsbMsDriveState_Disconnected);
sl@0
   444
		
sl@0
   445
			test(KErrNone == gMgr->Connect(0));
sl@0
   446
			test(KErrNone == gMgr->Connect(0)); // ensure it can be called more than once
sl@0
   447
			NEXT(EStepConnecting);
sl@0
   448
			break;
sl@0
   449
		
sl@0
   450
		case EStepConnecting:
sl@0
   451
			test(status==EUsbMsDriveState_Connecting);
sl@0
   452
			CActiveScheduler::Stop();
sl@0
   453
			break;
sl@0
   454
sl@0
   455
		default:
sl@0
   456
			break;
sl@0
   457
		}
sl@0
   458
		
sl@0
   459
	RDebug::Print(_L("<< PropertyHandlers::DriveStatus"));
sl@0
   460
	}
sl@0
   461
sl@0
   462
LOCAL_C void doTestL()
sl@0
   463
	{
sl@0
   464
	test.Start(_L("MSDrive1"));
sl@0
   465
	
sl@0
   466
	CActiveScheduler* sched = new(ELeave) CActiveScheduler;
sl@0
   467
	CleanupStack::PushL(sched);
sl@0
   468
	CActiveScheduler::Install(sched);
sl@0
   469
sl@0
   470
	RArray<TInt> driveMap;
sl@0
   471
	CleanupClosePushL(driveMap);
sl@0
   472
	driveMap.AppendL(gDrive1);
sl@0
   473
	driveMap.AppendL(gDrive2);
sl@0
   474
	
sl@0
   475
	gMgr = CDriveManager::NewL(driveMap);
sl@0
   476
	CleanupStack::PushL(gMgr);
sl@0
   477
	TInt err = KErrGeneral;
sl@0
   478
	CMassStorageDrive* drive1 = gMgr->Drive(0,err);
sl@0
   479
	test(err == KErrNone);
sl@0
   480
sl@0
   481
	///////////////////////////////////////////////////////////////////////////	
sl@0
   482
	test.Next(_L("Check initial state"));	
sl@0
   483
	test(CMassStorageDrive::EDisconnected==drive1->MountState());
sl@0
   484
	test(CMassStorageDrive::EErrDisMounted==drive1->DriveState());
sl@0
   485
	test(0==drive1->KBytesRead());
sl@0
   486
	test(0==drive1->KBytesWritten());
sl@0
   487
	test(EFalse==drive1->IsMediaChanged());
sl@0
   488
sl@0
   489
	///////////////////////////////////////////////////////////////////////////	
sl@0
   490
	test.Next(_L("Ensure Read/Write/Caps don't work when disconnected"));	
sl@0
   491
	
sl@0
   492
	const TInt KNoBytes = 1000;
sl@0
   493
	TBuf8<KNoBytes> buf;
sl@0
   494
	TLocalDriveCapsV4 caps;
sl@0
   495
	test(KErrDisconnected==drive1->Read(0,0,buf));
sl@0
   496
	test(KErrDisconnected==drive1->Write(0,buf));
sl@0
   497
	test(KErrDisconnected==drive1->Caps(caps));
sl@0
   498
sl@0
   499
	///////////////////////////////////////////////////////////////////////////	
sl@0
   500
	test.Next(_L("Test EConnecting state"));	
sl@0
   501
sl@0
   502
	drive1->SetMountConnecting();
sl@0
   503
	test(CMassStorageDrive::EConnecting==drive1->MountState());
sl@0
   504
	test(KErrDisconnected==drive1->Read(0,0,buf));
sl@0
   505
	test(KErrDisconnected==drive1->Write(0,buf));
sl@0
   506
	test(KErrDisconnected==drive1->Caps(caps));
sl@0
   507
sl@0
   508
	///////////////////////////////////////////////////////////////////////////	
sl@0
   509
	test.Next(_L("Test EDisconnecting state"));	
sl@0
   510
sl@0
   511
	drive1->SetMountDisconnecting();
sl@0
   512
	test(CMassStorageDrive::EDisconnecting==drive1->MountState());
sl@0
   513
	test(KErrDisconnected==drive1->Read(0,0,buf));
sl@0
   514
	test(KErrDisconnected==drive1->Write(0,buf));
sl@0
   515
	test(KErrDisconnected==drive1->Caps(caps));
sl@0
   516
sl@0
   517
	///////////////////////////////////////////////////////////////////////////	
sl@0
   518
	test.Next(_L("Test EConnected state"));	
sl@0
   519
sl@0
   520
	CTestProxyDrive* proxyDrive = new(ELeave) CTestProxyDrive(*gMgr);
sl@0
   521
	CleanupStack::PushL(proxyDrive);
sl@0
   522
	
sl@0
   523
	TBool mediaChanged = EFalse;
sl@0
   524
	test(KErrNone==gMgr->RegisterDrive(*proxyDrive, mediaChanged, 0));
sl@0
   525
	test(CMassStorageDrive::EConnected==drive1->MountState());
sl@0
   526
sl@0
   527
	///////////////////////////////////////////////////////////////////////////	
sl@0
   528
	test.Next(_L("Test SetCritical"));	
sl@0
   529
	test(CMassStorageDrive::EIdle==drive1->DriveState());
sl@0
   530
	test(KErrNone==drive1->SetCritical(ETrue));
sl@0
   531
	test(CMassStorageDrive::EActive==drive1->DriveState());
sl@0
   532
	test(KErrNone==drive1->SetCritical(EFalse));
sl@0
   533
	test(CMassStorageDrive::EIdle==drive1->DriveState());
sl@0
   534
sl@0
   535
	///////////////////////////////////////////////////////////////////////////	
sl@0
   536
	test.Next(_L("Test that ProxyDrive is called"));	
sl@0
   537
	
sl@0
   538
	CTestProxyDrive::iRetval = KErrNone;
sl@0
   539
sl@0
   540
	// Test that bytesRead is incremented correctly
sl@0
   541
	// when the count increments from 999 to 1000:
sl@0
   542
	test(KErrNone==drive1->Read(0,999,buf));
sl@0
   543
	test(0==drive1->KBytesRead());
sl@0
   544
	test(KErrNone==drive1->Read(0,1,buf));
sl@0
   545
	test(1==drive1->KBytesRead());
sl@0
   546
		
sl@0
   547
	buf.SetLength(KNoBytes);
sl@0
   548
	test(KErrNone==drive1->Write(0,buf));
sl@0
   549
	test(KErrNone==drive1->Caps(caps));
sl@0
   550
	// Write was called when EIdle, should restore state to EIdle
sl@0
   551
	// after transient EActive state.
sl@0
   552
	test(CMassStorageDrive::EIdle==drive1->DriveState());
sl@0
   553
sl@0
   554
	CTestProxyDrive::iRetval = KErrDied;  // arbitrary test value
sl@0
   555
	CTestProxyDrive::iRetval_caps = KErrDied;
sl@0
   556
	test(KErrDied==drive1->Read(0,0,buf));
sl@0
   557
	test(KErrDied==drive1->Write(0,buf));
sl@0
   558
	test(KErrDied==drive1->Caps(caps));
sl@0
   559
	CTestProxyDrive::iRetval = KErrNone;
sl@0
   560
	CTestProxyDrive::iRetval_caps = KErrNone;
sl@0
   561
sl@0
   562
	test.Next(_L("Test IsMediaChanged"));	
sl@0
   563
	test(EFalse==drive1->IsMediaChanged(ETrue));
sl@0
   564
	test(EFalse==drive1->IsMediaChanged(EFalse));
sl@0
   565
sl@0
   566
	///////////////////////////////////////////////////////////////////////////	
sl@0
   567
	
sl@0
   568
	CPropertyWatch::NewLC(EUsbMsDriveState_KBytesRead, PropertyHandlers::Read);
sl@0
   569
	CPropertyWatch::NewLC(EUsbMsDriveState_KBytesWritten, PropertyHandlers::Written);
sl@0
   570
	CPropertyWatch::NewLC(EUsbMsDriveState_DriveStatus, PropertyHandlers::DriveStatus);
sl@0
   571
sl@0
   572
	///////////////////////////////////////////////////////////////////////////	
sl@0
   573
	
sl@0
   574
	NEXT(EStepRead0);
sl@0
   575
	CActiveScheduler::Start();
sl@0
   576
	
sl@0
   577
	///////////////////////////////////////////////////////////////////////////	
sl@0
   578
sl@0
   579
	test.Printf(_L("\nCLEANING UP\n"));
sl@0
   580
sl@0
   581
	CleanupStack::PopAndDestroy(3); //CPropertyWatch x 3
sl@0
   582
	CleanupStack::PopAndDestroy(proxyDrive); 
sl@0
   583
	CleanupStack::PopAndDestroy(gMgr); 
sl@0
   584
	CleanupStack::PopAndDestroy(&driveMap); 
sl@0
   585
	CleanupStack::PopAndDestroy(sched); 
sl@0
   586
	
sl@0
   587
	return;	
sl@0
   588
	}
sl@0
   589
sl@0
   590
GLDEF_C TInt E32Main()
sl@0
   591
	{
sl@0
   592
	__UHEAP_MARK;
sl@0
   593
	CTrapCleanup* cleanup=CTrapCleanup::New();
sl@0
   594
	
sl@0
   595
	TRAPD(error,doTestL());
sl@0
   596
	if (error)
sl@0
   597
		test.Printf(_L("Leave occurred; code=%d\n"), error);
sl@0
   598
	
sl@0
   599
	test.End();	// output success/fail
sl@0
   600
	test.Close();
sl@0
   601
sl@0
   602
	delete cleanup;
sl@0
   603
	__UHEAP_MARKEND;
sl@0
   604
	return 0;
sl@0
   605
	}