os/kernelhwsrv/kerneltest/e32test/thread/t_thread.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
// Copyright (c) 1995-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
// e32test\thread\t_thread.cpp
sl@0
    15
// Overview:
sl@0
    16
// Tests the RThread class
sl@0
    17
// API Information:
sl@0
    18
// RThread, RUndertaker
sl@0
    19
// Details:
sl@0
    20
// - Create a thread, verify its priority, change the priority and verify results.
sl@0
    21
// - Verify naming and renaming threads works as expected.
sl@0
    22
// - Test logging on, resuming and closing a thread. Verify results are as expected.
sl@0
    23
// - Test creating threads with a variety of invalid parameters. Verify results.
sl@0
    24
// - Test the RUndertaker methods: create some threads, logon to the undertaker,
sl@0
    25
// verify results upon killing a thread and setting the thread handle.
sl@0
    26
// - Check kernel allocation when creating threads and undertakers. Verify the
sl@0
    27
// heap has not been corrupted.
sl@0
    28
// - Run a thread multiple times, panic within the thread, panic external to the
sl@0
    29
// thread and exit a thread in a variety of ways. Verify results are as expected.
sl@0
    30
// - Create a semaphore and some threads, verify the threads can wait on and signal
sl@0
    31
// the semaphore.
sl@0
    32
// - Test unclosed but completed threads.
sl@0
    33
// - Suspend and resume some threads in a variety of ways, verify results are as
sl@0
    34
// expected.
sl@0
    35
// - Test thread duplication.
sl@0
    36
// - Test opening a thread using an full name, perform various tests by finding, 
sl@0
    37
// killing, closing, recreating etc. Verify the results are as expected.
sl@0
    38
// - Test creating a thread using a duplicate name then reuse the thread with a
sl@0
    39
// valid name. Verify results are as expected.
sl@0
    40
// - Verify that a panicked thread releases an existing mutex.
sl@0
    41
// - Test thread ID: attempt to open a nonexistent thread by ID, verify different
sl@0
    42
// threads have different IDs, verify open by ID works as expected.
sl@0
    43
// - Test RThread::StackInfo(), print results and verify results are as expected.
sl@0
    44
// Platforms/Drives/Compatibility:
sl@0
    45
// All.
sl@0
    46
// Assumptions/Requirement/Pre-requisites:
sl@0
    47
// Failures and causes:
sl@0
    48
// Base Port information:
sl@0
    49
// 
sl@0
    50
//
sl@0
    51
sl@0
    52
#define __E32TEST_EXTENSION__
sl@0
    53
#include <e32test.h>
sl@0
    54
#include <e32panic.h>
sl@0
    55
#include <e32svr.h>
sl@0
    56
#include <u32hal.h>
sl@0
    57
#include <e32atomics.h>
sl@0
    58
#include <e32def.h>
sl@0
    59
#include <e32def_private.h>
sl@0
    60
#include "../misc/prbs.h"
sl@0
    61
sl@0
    62
const TInt KNumThreads=20;
sl@0
    63
sl@0
    64
const TInt KExitPanicNum=999;
sl@0
    65
const TInt KHeapSize=0x200;
sl@0
    66
const TInt KThreadReturnValue=9999;
sl@0
    67
const TInt KTerminationReason=1234;
sl@0
    68
const TInt KKillReason=4321;  
sl@0
    69
enum TInstruction {ENormal,EInstrPanic,EWait};
sl@0
    70
sl@0
    71
const TInt KWaitTime=800000;
sl@0
    72
sl@0
    73
class TReadInfo
sl@0
    74
	{
sl@0
    75
public:
sl@0
    76
	TDesC* tdesc;
sl@0
    77
	TPtrC* tptrc;
sl@0
    78
	TDes* tdes;
sl@0
    79
	TPtr* tptr;
sl@0
    80
	HBufC* hbufc;
sl@0
    81
	TBufC<0x20>* tbufc;
sl@0
    82
	TBuf<0x20>* tbuf;
sl@0
    83
	TPtr* tptrdes;
sl@0
    84
	TAny* anAddress;
sl@0
    85
	};
sl@0
    86
sl@0
    87
LOCAL_D RTest test(_L("T_THREAD"));
sl@0
    88
LOCAL_D RTest rtest(_L("Read thread tests"));
sl@0
    89
LOCAL_D	RTest wtest(_L("Write thread tests"));
sl@0
    90
sl@0
    91
#define rtest(x) rtest(x,__LINE__)
sl@0
    92
#define wtest(x) wtest(x,__LINE__)
sl@0
    93
sl@0
    94
LOCAL_C TInt LoopyThread(TAny*)
sl@0
    95
	{
sl@0
    96
	
sl@0
    97
	FOREVER
sl@0
    98
		User::AfterHighRes(1000);
sl@0
    99
	}
sl@0
   100
sl@0
   101
LOCAL_D void testUndertaker(TOwnerType anOwnerType)
sl@0
   102
//
sl@0
   103
// Test RThreadWatcher
sl@0
   104
//
sl@0
   105
	{
sl@0
   106
sl@0
   107
	RThread thread1;
sl@0
   108
	TInt r;
sl@0
   109
	test.Start(_L("Test the RUndertaker class"));
sl@0
   110
	test.Next(_L("Create a thread"));
sl@0
   111
//	if (anOwnerType==EOwnerThread)
sl@0
   112
//		User::SetDebugMask(0x8000867c);
sl@0
   113
	r=thread1.Create(_L("Loopy1"),LoopyThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)NULL,anOwnerType);
sl@0
   114
	test(r==KErrNone);
sl@0
   115
	thread1.Resume();
sl@0
   116
sl@0
   117
	TRequestStatus stat1;
sl@0
   118
	TInt threadHandle1;
sl@0
   119
	RThread w1;
sl@0
   120
	RUndertaker u1;
sl@0
   121
	test.Next(_L("Create an RUndertaker"));
sl@0
   122
	r=u1.Create();
sl@0
   123
	test(r==KErrNone);
sl@0
   124
	test.Next(_L("Logon to RUndertaker"));
sl@0
   125
	r=u1.Logon(stat1,threadHandle1);
sl@0
   126
	test(r==KErrNone);
sl@0
   127
	test.Next(_L("Logon again & check we're rejected"));
sl@0
   128
	r=u1.Logon(stat1,threadHandle1);
sl@0
   129
	test(r==KErrInUse);
sl@0
   130
	test.Next(_L("Cancel logon to RUndertaker"));
sl@0
   131
	r=u1.LogonCancel();
sl@0
   132
	test(r==KErrNone);
sl@0
   133
	test(stat1==KErrCancel);
sl@0
   134
sl@0
   135
	test.Next(_L("Logon to RUndertaker again"));
sl@0
   136
	u1.Logon(stat1,threadHandle1);
sl@0
   137
	
sl@0
   138
	test.Next(_L("Create another thread"));
sl@0
   139
	RThread thread2;
sl@0
   140
	r=thread2.Create(_L("Loopy2"),LoopyThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)NULL,anOwnerType);
sl@0
   141
	test(r==KErrNone);
sl@0
   142
	thread2.Resume();
sl@0
   143
sl@0
   144
	TRequestStatus stat2;
sl@0
   145
	TInt threadHandle2;
sl@0
   146
	RThread w2;
sl@0
   147
	RUndertaker u2;
sl@0
   148
	test.Next(_L("Create another RUndertaker"));
sl@0
   149
	r=u2.Create();
sl@0
   150
	test(r==KErrNone);
sl@0
   151
	test.Next(_L("Logon to RUndertaker"));
sl@0
   152
	r=u2.Logon(stat2,threadHandle2);
sl@0
   153
	test(r==KErrNone);
sl@0
   154
sl@0
   155
	test.Next(_L("Create yet another thread"));
sl@0
   156
	RThread thread3;
sl@0
   157
	r=thread3.Create(_L("Loopy3"),LoopyThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)NULL,anOwnerType);
sl@0
   158
	test(r==KErrNone);
sl@0
   159
	thread3.Resume();
sl@0
   160
sl@0
   161
	test.Next(_L("Kill the first thread & check the undertakers"));
sl@0
   162
	thread1.Kill(0x489);
sl@0
   163
	thread1.Close();
sl@0
   164
sl@0
   165
	User::WaitForRequest(stat1);
sl@0
   166
	User::WaitForRequest(stat2);
sl@0
   167
	test(stat1==KErrDied);
sl@0
   168
	test(stat2==KErrDied);
sl@0
   169
sl@0
   170
	RThread keep1;
sl@0
   171
	RThread keep2;
sl@0
   172
	test.Next(_L("Set the RThread handles"));
sl@0
   173
	keep1.SetHandle(threadHandle1);
sl@0
   174
	keep2.SetHandle(threadHandle2);
sl@0
   175
sl@0
   176
	test.Next(_L("Test the exit reasons"));
sl@0
   177
	test(keep1.ExitReason()==0x489);
sl@0
   178
	test(keep2.ExitReason()==0x489);
sl@0
   179
//	test.Printf(_L("Thread name %S\n"),&(w1.Name()));
sl@0
   180
sl@0
   181
	test.Next(_L("Logon again with both watchers"));
sl@0
   182
	r=u1.Logon(stat1,threadHandle1);
sl@0
   183
	test(r==KErrNone);
sl@0
   184
	r=u2.Logon(stat2,threadHandle2);
sl@0
   185
	test(r==KErrNone);
sl@0
   186
sl@0
   187
	test.Next(_L("Kill the 3rd thread & check the undertakers"));
sl@0
   188
	thread3.Kill(0x999);
sl@0
   189
	thread3.Close();
sl@0
   190
sl@0
   191
	User::WaitForRequest(stat1);
sl@0
   192
	User::WaitForRequest(stat2);
sl@0
   193
	test(stat1==KErrDied);
sl@0
   194
	test(stat2==KErrDied);
sl@0
   195
sl@0
   196
	test.Next(_L("Set the RThread handles"));
sl@0
   197
	w1.SetHandle(threadHandle1);
sl@0
   198
	w2.SetHandle(threadHandle2);
sl@0
   199
sl@0
   200
	test.Next(_L("Test the exit reasons"));
sl@0
   201
	test(w1.ExitReason()==0x999);
sl@0
   202
	test(w2.ExitReason()==0x999);
sl@0
   203
//	test.Printf(_L("Thread name %S\n"),&(w1.Name()));
sl@0
   204
	w1.Close();
sl@0
   205
	CLOSE_AND_WAIT(w2);
sl@0
   206
sl@0
   207
	test.Next(_L("Logon again with both undertakers"));
sl@0
   208
	r=u1.Logon(stat1,threadHandle1);
sl@0
   209
	test(r==KErrNone);
sl@0
   210
	r=u2.Logon(stat2,threadHandle2);
sl@0
   211
	test(r==KErrNone);
sl@0
   212
sl@0
   213
	test.Next(_L("Kill the 2nd thread & check the undertakers"));
sl@0
   214
	thread2.Kill(0x707);
sl@0
   215
	thread2.Close();
sl@0
   216
sl@0
   217
	User::WaitForRequest(stat1);
sl@0
   218
	User::WaitForRequest(stat2);
sl@0
   219
	test(stat1==KErrDied);
sl@0
   220
	test(stat2==KErrDied);
sl@0
   221
sl@0
   222
	test.Next(_L("Set the RThread handles"));
sl@0
   223
	w1.SetHandle(threadHandle1);
sl@0
   224
	w2.SetHandle(threadHandle2);
sl@0
   225
sl@0
   226
	test.Next(_L("Test the exit reasons"));
sl@0
   227
	test(w1.ExitReason()==0x707);
sl@0
   228
	test(w2.ExitReason()==0x707);
sl@0
   229
//	test.Printf(_L("Thread name %S\n"),&(w1.Name()));
sl@0
   230
sl@0
   231
	test.Next(_L("Check kernel allocation"));
sl@0
   232
	test.Next(_L("Please wait while I create & close masses of threads"));
sl@0
   233
	RThread t[KNumThreads];
sl@0
   234
	TInt j;
sl@0
   235
	for (j=0; j<KNumThreads; j++)
sl@0
   236
		{
sl@0
   237
		TBuf<0x10> name;
sl@0
   238
		name.Format(_L("LoopyThread%d"),j);
sl@0
   239
		test(t[j].Create(name, LoopyThread, KDefaultStackSize, KHeapSize, KHeapSize, (TAny*)NULL,anOwnerType)==KErrNone);
sl@0
   240
		}
sl@0
   241
	for (j=0; j<KNumThreads-1; j++)
sl@0
   242
		{
sl@0
   243
		t[j].Kill(666);
sl@0
   244
		CLOSE_AND_WAIT(t[j]);
sl@0
   245
		}
sl@0
   246
sl@0
   247
	test.Next(_L("Please wait while I close & create some undertakers"));
sl@0
   248
	u1.Close();
sl@0
   249
	u2.Close();
sl@0
   250
	r=u1.Create();
sl@0
   251
	test(r==KErrNone);
sl@0
   252
	r=u2.Create();
sl@0
   253
	test(r==KErrNone);
sl@0
   254
sl@0
   255
	test.Next(_L("Mark kernel heap"));
sl@0
   256
	__KHEAP_MARK;
sl@0
   257
sl@0
   258
	test.Next(_L("Create thread"));
sl@0
   259
	RThread threadx;
sl@0
   260
	r=threadx.Create(_L("Loopyx"),LoopyThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)NULL,anOwnerType);
sl@0
   261
	test(r==KErrNone);
sl@0
   262
	test.Next(_L("Resume thread"));
sl@0
   263
	threadx.Resume();
sl@0
   264
sl@0
   265
	test.Next(_L("Create undertaker"));
sl@0
   266
	TRequestStatus statx;
sl@0
   267
	TInt threadHandlex;
sl@0
   268
	RUndertaker ux;
sl@0
   269
	r=ux.Create();
sl@0
   270
	test(r==KErrNone);
sl@0
   271
	test.Next(_L("Logon to undertaker"));
sl@0
   272
	r=ux.Logon(statx,threadHandlex);
sl@0
   273
	test(r==KErrNone);
sl@0
   274
	test.Next(_L("Kill thread"));
sl@0
   275
	threadx.Kill(0x666);
sl@0
   276
	threadx.Close();
sl@0
   277
	User::WaitForRequest(statx);
sl@0
   278
	test(statx==KErrDied);
sl@0
   279
	test.Next(_L("Close thread"));
sl@0
   280
	RThread wx;
sl@0
   281
	wx.SetHandle(threadHandlex);
sl@0
   282
	CLOSE_AND_WAIT(wx);
sl@0
   283
sl@0
   284
	test.Next(_L("Close undertaker"));
sl@0
   285
	ux.Close();
sl@0
   286
sl@0
   287
	test.Next(_L("Check kernel heap"));
sl@0
   288
	__KHEAP_MARKEND;
sl@0
   289
	w1.Close();
sl@0
   290
	CLOSE_AND_WAIT(w2);
sl@0
   291
	keep1.Close();
sl@0
   292
	CLOSE_AND_WAIT(keep2);
sl@0
   293
	t[KNumThreads-1].Kill(666);
sl@0
   294
	CLOSE_AND_WAIT(t[KNumThreads-1]);
sl@0
   295
sl@0
   296
	test.Next(_L("Close RUndertakers"));
sl@0
   297
	u1.Close();
sl@0
   298
	u2.Close();
sl@0
   299
	test.End();
sl@0
   300
	}
sl@0
   301
sl@0
   302
volatile TInt IFLAG;
sl@0
   303
sl@0
   304
TInt InstructionThread(TAny* anInstruction)
sl@0
   305
	{
sl@0
   306
	__e32_atomic_store_ord32(&IFLAG, 1);
sl@0
   307
	RThread::Rendezvous(KErrNone);
sl@0
   308
	TInstruction what=(TInstruction)(TInt)anInstruction;
sl@0
   309
	if (what==EInstrPanic)
sl@0
   310
		User::Panic(_L("Hello"), KExitPanicNum);
sl@0
   311
	if (what==ENormal)
sl@0
   312
		return(KThreadReturnValue);
sl@0
   313
	User::After(500000);
sl@0
   314
	return(KErrNone);
sl@0
   315
	}
sl@0
   316
sl@0
   317
TInt StartInstructionThread(RThread& aT, const TDesC& aName, TInt aInstruction, TOwnerType aOwnerType, TRequestStatus* aL, TRequestStatus* aR)
sl@0
   318
	{
sl@0
   319
	TInt r = aT.Create(aName, &InstructionThread, KDefaultStackSize, KHeapSize, KHeapSize, (TAny*)aInstruction, aOwnerType);
sl@0
   320
	if (r!=KErrNone)
sl@0
   321
		return r;
sl@0
   322
	if (aL)
sl@0
   323
		{
sl@0
   324
		aT.Logon(*aL);
sl@0
   325
		TInt s = aL->Int();
sl@0
   326
		test_Equal(s, KRequestPending);
sl@0
   327
		}
sl@0
   328
	if (aR)
sl@0
   329
		{
sl@0
   330
		aT.Rendezvous(*aR);
sl@0
   331
		TInt s = aR->Int();
sl@0
   332
		test_Equal(s, KRequestPending);
sl@0
   333
		aT.Resume();
sl@0
   334
		User::WaitForRequest(*aR);
sl@0
   335
		s = aR->Int();
sl@0
   336
		test_KErrNone(s);
sl@0
   337
		}
sl@0
   338
	return r;
sl@0
   339
	}
sl@0
   340
sl@0
   341
sl@0
   342
LOCAL_D TInt test4Thread(TAny *aSem)
sl@0
   343
//
sl@0
   344
// Wait to be released on the semaphore.
sl@0
   345
// Then release the semaphore.
sl@0
   346
//
sl@0
   347
	{
sl@0
   348
sl@0
   349
	RSemaphore& sem=(*(RSemaphore*)aSem);
sl@0
   350
	sem.Wait();
sl@0
   351
	sem.Signal();
sl@0
   352
	return(KErrNone);
sl@0
   353
	}
sl@0
   354
sl@0
   355
TInt BadPriority(TAny* aThread)
sl@0
   356
	{
sl@0
   357
	((RThread*)aThread)->SetPriority(EPriorityNull);
sl@0
   358
	return KErrNone;
sl@0
   359
	}
sl@0
   360
sl@0
   361
_LIT(KLitRomString,"RomStringRomStringRomStringRomStringRomStringRomStringRomString");
sl@0
   362
sl@0
   363
LOCAL_C TInt BadFullNameThread(TAny* aPar)
sl@0
   364
	{
sl@0
   365
	RThread thread;
sl@0
   366
	
sl@0
   367
	switch ((TInt)aPar)
sl@0
   368
		{
sl@0
   369
		case 0:
sl@0
   370
			{
sl@0
   371
			HBufC* hBuf = HBufC::New(5);//Size 5 is not sufficient. thread.FullName should panic.
sl@0
   372
			test(NULL != hBuf);
sl@0
   373
			RBuf rBuf(hBuf);
sl@0
   374
			thread.FullName(rBuf);
sl@0
   375
			rBuf.Close();
sl@0
   376
			}
sl@0
   377
			return(KErrNone);
sl@0
   378
sl@0
   379
		case 1:
sl@0
   380
			{
sl@0
   381
			TPtr ptr((TText*)(KLitRomString.iBuf), KLitRomString.iTypeLength);
sl@0
   382
			// Passing descriptor whose data is in ROM. This may behave in different ways
sl@0
   383
			// on differrent platforms. Here, we just check that Kernel is safe.
sl@0
   384
			thread.FullName(ptr);
sl@0
   385
			}
sl@0
   386
			return(KErrNone);
sl@0
   387
		}
sl@0
   388
	return(KErrArgument);
sl@0
   389
	}
sl@0
   390
sl@0
   391
sl@0
   392
LOCAL_D void test1()
sl@0
   393
//
sl@0
   394
// Test 1
sl@0
   395
//
sl@0
   396
	{
sl@0
   397
	
sl@0
   398
	__UHEAP_MARK;
sl@0
   399
	RThread thread;
sl@0
   400
	TRequestStatus stat;
sl@0
   401
	TInt r;
sl@0
   402
sl@0
   403
	test.Start(_L("Close without create"));
sl@0
   404
	thread.Close();
sl@0
   405
	
sl@0
   406
	test.Next(_L("Create ENormal"));
sl@0
   407
	r = StartInstructionThread(thread, _L("Thread"), ENormal, EOwnerProcess, 0, 0);
sl@0
   408
	test_KErrNone(r);
sl@0
   409
sl@0
   410
	test.Next(_L("Test priorities"));
sl@0
   411
	test(thread.Priority()==EPriorityNormal);
sl@0
   412
	thread.SetPriority(EPriorityRealTime);	// WINS will commute this to EPriorityMuchMore
sl@0
   413
#if defined(__EPOC32__)
sl@0
   414
	test(thread.Priority()==EPriorityRealTime);
sl@0
   415
#endif
sl@0
   416
	thread.SetPriority(EPriorityMuchMore);
sl@0
   417
	test(thread.Priority()==EPriorityMuchMore);
sl@0
   418
//	thread.SetPriority(EPriorityNull);
sl@0
   419
	RThread badThread;
sl@0
   420
	r = badThread.Create(_L("Bad Priority"),BadPriority,KDefaultStackSize,KHeapSize,KHeapSize,&thread);
sl@0
   421
	test(r==KErrNone);
sl@0
   422
	badThread.Logon(stat);
sl@0
   423
	test(stat==KRequestPending);
sl@0
   424
	badThread.Resume();
sl@0
   425
	User::WaitForRequest(stat);
sl@0
   426
	test(stat==EBadPriority);
sl@0
   427
	test(badThread.ExitCategory()==_L("KERN-EXEC"));
sl@0
   428
	test(badThread.ExitReason()==EBadPriority);
sl@0
   429
	test(badThread.ExitType()==EExitPanic);
sl@0
   430
	CLOSE_AND_WAIT(badThread);
sl@0
   431
	test(thread.Priority()==EPriorityMuchMore);
sl@0
   432
sl@0
   433
#if defined(__EPOC32__)
sl@0
   434
	test.Next(_L("Test setting process priority from thread"));
sl@0
   435
	test(thread.ProcessPriority()==EPriorityForeground);
sl@0
   436
	thread.SetProcessPriority(EPriorityHigh);
sl@0
   437
	test(thread.ProcessPriority()==EPriorityHigh);
sl@0
   438
	test(RProcess().Priority()==EPriorityHigh);
sl@0
   439
	thread.SetProcessPriority(EPriorityForeground);
sl@0
   440
	test(thread.ProcessPriority()==EPriorityForeground);
sl@0
   441
	test(RProcess().Priority()==EPriorityForeground);
sl@0
   442
#endif
sl@0
   443
sl@0
   444
	TBuf<0x100> name;
sl@0
   445
	test.Next(_L("Test thread name"));
sl@0
   446
	test(thread.Name()==_L("Thread"));
sl@0
   447
	test.Next(_L("Get owning process name"));
sl@0
   448
	RProcess p;
sl@0
   449
	test(thread.Process(p)==KErrNone);
sl@0
   450
	name=p.Name();
sl@0
   451
	name.Append(_L("::"));
sl@0
   452
	name.Append(thread.Name());
sl@0
   453
	test.Next(_L("Test fullname - via TFullName RHandleBase::FullName"));
sl@0
   454
	test(thread.FullName().CompareF(name)==0);
sl@0
   455
sl@0
   456
	test.Next(_L("Test fullname - via void RHandleBase::FullName(TDes& aName)"));
sl@0
   457
	HBufC* hBuf = HBufC::New(100);
sl@0
   458
	test(NULL != hBuf);
sl@0
   459
	TPtr ptr = hBuf->Des();
sl@0
   460
	thread.FullName(ptr);
sl@0
   461
	test(ptr.CompareF(name)==0);
sl@0
   462
	RBuf rBuf(hBuf);
sl@0
   463
	thread.FullName(rBuf);
sl@0
   464
	test(rBuf.CompareF(name)==0);
sl@0
   465
	rBuf.Close();
sl@0
   466
sl@0
   467
	test.Next(_L("Test void RHandleBase::FullName(TDes& aName) when aName is too short"));
sl@0
   468
	TInt aaa=badThread.Create(_L("BadFullNameThread1"),BadFullNameThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)0);
sl@0
   469
	test(aaa==KErrNone);
sl@0
   470
	badThread.Logon(stat);
sl@0
   471
	test(badThread.ExitType()==EExitPending);
sl@0
   472
	badThread.Resume();
sl@0
   473
	User::WaitForRequest(stat);
sl@0
   474
	test(badThread.ExitCategory()==_L("KERN-EXEC"));
sl@0
   475
	test(badThread.ExitReason()==EKUDesSetLengthOverflow);
sl@0
   476
	test(badThread.ExitType()==EExitPanic);
sl@0
   477
	CLOSE_AND_WAIT(badThread);
sl@0
   478
sl@0
   479
	test.Next(_L("Test void RHandleBase::FullName(TDes& aName) where aName has data in ROM "));
sl@0
   480
	aaa=badThread.Create(_L("BadFullNameThread2"),BadFullNameThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)1);
sl@0
   481
	test(aaa==KErrNone);
sl@0
   482
	badThread.Logon(stat);
sl@0
   483
	test(badThread.ExitType()==EExitPending);
sl@0
   484
	badThread.Resume();
sl@0
   485
	User::WaitForRequest(stat);
sl@0
   486
	test.Printf(_L("BadFullNameThread2 exited with ExitReason=%d and ExitType=%d\n"),badThread.ExitReason(),badThread.ExitType());
sl@0
   487
	CLOSE_AND_WAIT(badThread);
sl@0
   488
sl@0
   489
	test.Next(_L("Rename current thread"));
sl@0
   490
	test(User::RenameThread(_L("renamed"))==KErrNone);
sl@0
   491
	name=p.Name();
sl@0
   492
	name.Append(_L("::"));
sl@0
   493
	RThread me;
sl@0
   494
	name.Append(me.Name());
sl@0
   495
	test(me.Name()==_L("renamed"));
sl@0
   496
	test(me.FullName().CompareF(name)==0);
sl@0
   497
sl@0
   498
	test.Next(_L("Test running exit types"));
sl@0
   499
	test(thread.ExitType()==EExitPending);
sl@0
   500
	test(thread.ExitReason()==0);
sl@0
   501
	// no getters for iUserHeap and iFrame
sl@0
   502
	test(thread.ExitCategory()==KNullDesC);
sl@0
   503
sl@0
   504
	test.Next(_L("Test logging on"));
sl@0
   505
	thread.Logon(stat);
sl@0
   506
	RThread t;
sl@0
   507
	test(t.RequestCount()==0);
sl@0
   508
	test(stat==KRequestPending);
sl@0
   509
	r=thread.LogonCancel(stat); // this generates a signal 
sl@0
   510
	test(r==KErrNone);
sl@0
   511
	test(stat==KErrNone);
sl@0
   512
	test(t.RequestCount()==1); // the request count is 1 due to the signal generated by LogonCancel
sl@0
   513
	test(thread.RequestCount()==0);
sl@0
   514
sl@0
   515
	test.Next(_L("Resuming thread"));
sl@0
   516
	thread.Resume();   
sl@0
   517
	test.Next(_L("Absorb cancel"));
sl@0
   518
	User::WaitForRequest(stat);	
sl@0
   519
	test.Next(_L("Test LogonCancel on dead thread is ok"));
sl@0
   520
	r=thread.LogonCancel(stat);
sl@0
   521
	test(r==KErrGeneral);
sl@0
   522
	test.Next(_L("Close thread"));
sl@0
   523
	CLOSE_AND_WAIT(thread);
sl@0
   524
	test.Next(_L("Close again"));
sl@0
   525
	thread.Close();
sl@0
   526
	thread.Close();
sl@0
   527
	thread.Close();
sl@0
   528
	thread.Close();
sl@0
   529
	__UHEAP_MARKEND;
sl@0
   530
	test.End();
sl@0
   531
	}
sl@0
   532
sl@0
   533
sl@0
   534
LOCAL_D void test2(TOwnerType anOwnerType)
sl@0
   535
//
sl@0
   536
// Test 2
sl@0
   537
//
sl@0
   538
	{                                  
sl@0
   539
sl@0
   540
	__UHEAP_MARK;
sl@0
   541
	RThread thread;
sl@0
   542
	TRequestStatus stat;
sl@0
   543
	TRequestStatus rstat;
sl@0
   544
	TInt r;
sl@0
   545
sl@0
   546
	test.Start(_L("Run thread 10 times"));
sl@0
   547
	for (TInt xx=0;xx<10;xx++)
sl@0
   548
		{
sl@0
   549
		test.Printf(_L("\r%02d"),xx);
sl@0
   550
		r = StartInstructionThread(thread, _L("Thread1"), ENormal, anOwnerType, &stat, 0);
sl@0
   551
		test_KErrNone(r);
sl@0
   552
		thread.Resume();
sl@0
   553
		User::WaitForRequest(stat);
sl@0
   554
		CLOSE_AND_WAIT(thread);
sl@0
   555
		}
sl@0
   556
	test.Printf(_L("\n"));
sl@0
   557
sl@0
   558
	test.Next(_L("Panic within thread"));
sl@0
   559
	r = StartInstructionThread(thread, _L("Thread2"), EInstrPanic, anOwnerType, &stat, 0);
sl@0
   560
	test_KErrNone(r);
sl@0
   561
	test(thread.ExitType()==EExitPending);
sl@0
   562
	thread.Resume();
sl@0
   563
	User::WaitForRequest(stat);
sl@0
   564
	test(thread.ExitCategory()==_L("Hello"));
sl@0
   565
	test(thread.ExitReason()==KExitPanicNum);
sl@0
   566
	test(thread.ExitType()==EExitPanic);
sl@0
   567
	CLOSE_AND_WAIT(thread);
sl@0
   568
sl@0
   569
	test.Next(_L("Panic external to thread"));
sl@0
   570
	TInt ijk;
sl@0
   571
	TUint seed[2] = { 0xadf85458, 0 };
sl@0
   572
	TUint maxcount = 0;
sl@0
   573
	for (ijk=0; ijk<8192; ++ijk)
sl@0
   574
		{
sl@0
   575
		if (!(ijk&255))
sl@0
   576
			test.Printf(_L("%d\n"), ijk);
sl@0
   577
		r = StartInstructionThread(thread, _L("Thread3"), EWait, anOwnerType, &stat, 0);
sl@0
   578
		test_KErrNone(r);
sl@0
   579
		__e32_atomic_store_ord32(&IFLAG, 0);
sl@0
   580
		thread.Resume();
sl@0
   581
		thread.SetPriority(EPriorityMore);
sl@0
   582
		if (maxcount==0)
sl@0
   583
			{
sl@0
   584
			while (__e32_atomic_load_acq32(&IFLAG)==0 && --maxcount!=0)
sl@0
   585
				{
sl@0
   586
				}
sl@0
   587
			maxcount = 0u - maxcount;
sl@0
   588
			test.Printf(_L("maxcount=%u\n"), maxcount);
sl@0
   589
			}
sl@0
   590
		else
sl@0
   591
			{
sl@0
   592
			TUint random = Random(seed);
sl@0
   593
			random %= maxcount;
sl@0
   594
			++random;
sl@0
   595
			while (__e32_atomic_load_acq32(&IFLAG)==0 && --random!=0)
sl@0
   596
				{
sl@0
   597
				}
sl@0
   598
			}
sl@0
   599
		thread.Panic(_L("panic"), 123);
sl@0
   600
		User::WaitForRequest(stat);
sl@0
   601
		test(thread.ExitCategory()==_L("panic"));
sl@0
   602
		test(thread.ExitReason()==123);
sl@0
   603
		test(thread.ExitType()==EExitPanic);
sl@0
   604
		CLOSE_AND_WAIT(thread);
sl@0
   605
		}
sl@0
   606
	
sl@0
   607
	test.Next(_L("Internal exit"));
sl@0
   608
	r = StartInstructionThread(thread, _L("Thread4"), ENormal, anOwnerType, &stat, 0);
sl@0
   609
	test_KErrNone(r);
sl@0
   610
	test(thread.ExitType()==EExitPending);
sl@0
   611
	thread.Resume();
sl@0
   612
	User::WaitForRequest(stat);
sl@0
   613
	test(thread.ExitCategory()==_L("Kill"));
sl@0
   614
	test(thread.ExitReason()==KThreadReturnValue);
sl@0
   615
	test(thread.ExitType()==EExitKill);
sl@0
   616
	CLOSE_AND_WAIT(thread);
sl@0
   617
sl@0
   618
	test.Next(_L("External terminate"));
sl@0
   619
	r = StartInstructionThread(thread, _L("Thread5"), EWait, anOwnerType, &stat, &rstat);
sl@0
   620
	test_KErrNone(r);
sl@0
   621
	test.Next(_L("Terminate"));
sl@0
   622
	thread.Terminate(KTerminationReason);
sl@0
   623
	test.Next(_L("Wait"));
sl@0
   624
	User::WaitForRequest(stat);
sl@0
   625
	test(thread.ExitCategory()==_L("Terminate"));
sl@0
   626
	test(thread.ExitReason()==KTerminationReason);
sl@0
   627
	test(thread.ExitType()==EExitTerminate);
sl@0
   628
	test.Next(_L("Close"));
sl@0
   629
	CLOSE_AND_WAIT(thread);
sl@0
   630
  
sl@0
   631
	test.Next(_L("External kill"));
sl@0
   632
	r = StartInstructionThread(thread, _L("Thread6"), EWait, anOwnerType, &stat, &rstat);
sl@0
   633
	test_KErrNone(r);
sl@0
   634
	thread.Suspend();
sl@0
   635
	thread.Resume();
sl@0
   636
	thread.Kill(KKillReason);
sl@0
   637
	User::WaitForRequest(stat);
sl@0
   638
	test(thread.ExitCategory()==_L("Kill"));
sl@0
   639
	test(thread.ExitReason()==KKillReason);
sl@0
   640
	test(thread.ExitType()==EExitKill);
sl@0
   641
	test.Next(_L("Kill again"));
sl@0
   642
	thread.Kill(KErrNone);
sl@0
   643
	thread.Kill(KErrNone);
sl@0
   644
	thread.Kill(KErrNone);
sl@0
   645
	CLOSE_AND_WAIT(thread);
sl@0
   646
	test.End();
sl@0
   647
  	__UHEAP_MARKEND;
sl@0
   648
	}
sl@0
   649
sl@0
   650
LOCAL_D void test3()
sl@0
   651
//
sl@0
   652
// Test 3.
sl@0
   653
//
sl@0
   654
	{
sl@0
   655
sl@0
   656
	test.Start(_L("Read across thread"));
sl@0
   657
	TReadInfo info;
sl@0
   658
	TPtrC des1=_L("tdesc");
sl@0
   659
	info.tdesc=(&des1);
sl@0
   660
	TPtrC ptr1=_L("tptrc");
sl@0
   661
	info.tptrc=&ptr1;
sl@0
   662
	TBuf<0x20> tdes(_L("tdes"));
sl@0
   663
	info.tdes=&tdes;
sl@0
   664
	TBuf<0x20> tptrbuf(_L("tptr"));
sl@0
   665
	TPtr tptr((TText*)tptrbuf.Ptr(),tptrbuf.Length(),tptrbuf.MaxLength());
sl@0
   666
	info.tptr=&tptr;
sl@0
   667
	TBuf<0x20> hbufc(_L("hbufc"));
sl@0
   668
	HBufC *pH=hbufc.Alloc();
sl@0
   669
	test(pH!=NULL);
sl@0
   670
	info.hbufc=pH;
sl@0
   671
	TBufC<0x20> tbufc(_L("tbufc"));
sl@0
   672
	info.tbufc=&tbufc;
sl@0
   673
	TBuf<0x20> tbuf(_L("tbuf"));
sl@0
   674
	info.tbuf=&tbuf;
sl@0
   675
	TBufC<0x20> tptrdes(_L("tptrdes"));
sl@0
   676
	TPtr des=tptrdes.Des();
sl@0
   677
	info.tptrdes=&des;
sl@0
   678
	TBuf<0x10> b(_L("Hello"));
sl@0
   679
	info.anAddress=(&b);
sl@0
   680
	info.anAddress= info.anAddress; //prevents warning (var set but never used)
sl@0
   681
	delete pH;
sl@0
   682
	test.End();
sl@0
   683
	}
sl@0
   684
sl@0
   685
LOCAL_D void test4()
sl@0
   686
//
sl@0
   687
// Test 4.
sl@0
   688
//
sl@0
   689
	{
sl@0
   690
sl@0
   691
	test.Start(_L("Create sempahore"));
sl@0
   692
	RSemaphore sem;
sl@0
   693
	TInt r=sem.CreateLocal(0);
sl@0
   694
	test(r==KErrNone);
sl@0
   695
//
sl@0
   696
	test.Next(_L("Create thread 1"));
sl@0
   697
	RThread t;
sl@0
   698
	r=t.Create(_L("Thread1"),test4Thread,KDefaultStackSize,KHeapSize,KHeapSize,&sem);
sl@0
   699
	test(r==KErrNone);
sl@0
   700
	t.Resume();
sl@0
   701
	t.Close();
sl@0
   702
//
sl@0
   703
	test.Next(_L("Create thread 2"));
sl@0
   704
	r=t.Create(_L("Thread2"),test4Thread,KDefaultStackSize,KHeapSize,KHeapSize,&sem);
sl@0
   705
	test(r==KErrNone);
sl@0
   706
	t.Resume();
sl@0
   707
	t.Close();
sl@0
   708
//
sl@0
   709
	test.Next(_L("Create thread 3"));
sl@0
   710
	r=t.Create(_L("Thread3"),test4Thread,KDefaultStackSize,KHeapSize,KHeapSize,&sem);
sl@0
   711
	test(r==KErrNone);
sl@0
   712
	t.Resume();
sl@0
   713
	t.Close();
sl@0
   714
//
sl@0
   715
	test.Next(_L("Release threads"));
sl@0
   716
	sem.Signal(3);
sl@0
   717
//
sl@0
   718
	test.Next(_L("Wait 1"));
sl@0
   719
	sem.Wait();
sl@0
   720
//
sl@0
   721
	test.Next(_L("Wait 2"));
sl@0
   722
	sem.Wait();
sl@0
   723
//
sl@0
   724
	test.Next(_L("Wait 2"));
sl@0
   725
	sem.Wait();
sl@0
   726
	sem.Close();
sl@0
   727
//
sl@0
   728
	test.End();
sl@0
   729
	}
sl@0
   730
sl@0
   731
TInt MinimalThread(TAny*)
sl@0
   732
//
sl@0
   733
// Minimal thread, used in test 5
sl@0
   734
//
sl@0
   735
	{
sl@0
   736
	return(KErrNone);
sl@0
   737
	}
sl@0
   738
sl@0
   739
LOCAL_D void test5()
sl@0
   740
//
sl@0
   741
// Test 5 - tests unclosed but completed threads
sl@0
   742
//
sl@0
   743
	{
sl@0
   744
sl@0
   745
	test.Start(_L("Start thread"));
sl@0
   746
	RThread thread1;
sl@0
   747
	test(thread1.Create(_L("Test Thread1"),MinimalThread,KDefaultStackSize,KHeapSize,KHeapSize,NULL)==KErrNone);
sl@0
   748
	TRequestStatus stat1;
sl@0
   749
	thread1.Logon(stat1);
sl@0
   750
	thread1.Resume();
sl@0
   751
	User::WaitForRequest(stat1);
sl@0
   752
	test(thread1.ExitType()==EExitKill);
sl@0
   753
	// 'missing'  thread1.Close();
sl@0
   754
sl@0
   755
	test.Next(_L("Start another thread"));
sl@0
   756
	RThread thread2;
sl@0
   757
	test(thread2.Create(_L("Test Thread2"),MinimalThread,KDefaultStackSize,KHeapSize,KHeapSize,NULL)==KErrNone);
sl@0
   758
	TRequestStatus stat2;
sl@0
   759
	thread2.Logon(stat2);
sl@0
   760
	thread2.Resume();
sl@0
   761
	User::WaitForRequest(stat2);  //Goes wrong here in build 48
sl@0
   762
	test(thread2.ExitType()==EExitKill);
sl@0
   763
	
sl@0
   764
	test.Next(_L("Close both threads"));
sl@0
   765
	CLOSE_AND_WAIT(thread2);
sl@0
   766
	CLOSE_AND_WAIT(thread1);
sl@0
   767
sl@0
   768
	test.End();
sl@0
   769
	}
sl@0
   770
sl@0
   771
LOCAL_D TInt test6Thread(TAny *anArg)
sl@0
   772
//
sl@0
   773
//
sl@0
   774
//
sl@0
   775
	{
sl@0
   776
	((RSemaphore*)anArg)->Wait();
sl@0
   777
	RThread t;
sl@0
   778
	RThread dup;
sl@0
   779
	dup.Duplicate(t);
sl@0
   780
	dup.Panic(_L("Test"),0);
sl@0
   781
sl@0
   782
	return KErrNone;
sl@0
   783
	}
sl@0
   784
sl@0
   785
void test6()
sl@0
   786
//
sl@0
   787
// Test thread duplication
sl@0
   788
//
sl@0
   789
	{
sl@0
   790
sl@0
   791
	test.Start(_L("Create thread"));
sl@0
   792
	RSemaphore sem;
sl@0
   793
	TInt r=sem.CreateLocal(0);
sl@0
   794
	test(r==KErrNone);
sl@0
   795
sl@0
   796
	RThread t;
sl@0
   797
	t.Create(_L("test6thread"),test6Thread,KDefaultStackSize,KHeapSize,KHeapSize,&sem);
sl@0
   798
	test.Next(_L("Resume thread"));
sl@0
   799
	TRequestStatus stat;
sl@0
   800
	t.Logon(stat);
sl@0
   801
	t.Resume();
sl@0
   802
	sem.Signal();
sl@0
   803
	User::WaitForRequest(stat);
sl@0
   804
	test.Next(_L("Close thread"));
sl@0
   805
	t.Close();
sl@0
   806
	sem.Close();
sl@0
   807
	test.End();
sl@0
   808
	}
sl@0
   809
sl@0
   810
RSemaphore gsem;
sl@0
   811
enum TThreadProgress { EBeforeStart, EStarted, EWaiting, EDoneWaiting, EFinished };
sl@0
   812
TThreadProgress progress=EBeforeStart;
sl@0
   813
LOCAL_D TInt test7thread(TAny * /*anArg*/)
sl@0
   814
//
sl@0
   815
//
sl@0
   816
//
sl@0
   817
	{
sl@0
   818
sl@0
   819
	progress=EStarted;
sl@0
   820
	progress=EWaiting;
sl@0
   821
	gsem.Wait();
sl@0
   822
	progress=EDoneWaiting;
sl@0
   823
	gsem.Wait();
sl@0
   824
	progress=EFinished;
sl@0
   825
	return KErrNone;
sl@0
   826
	}
sl@0
   827
sl@0
   828
void test7()
sl@0
   829
//
sl@0
   830
//	Suspend/ Resume tests
sl@0
   831
//
sl@0
   832
	{
sl@0
   833
sl@0
   834
	TInt r=gsem.CreateLocal(0);
sl@0
   835
	test(r==KErrNone);
sl@0
   836
	test.Start(_L("Create thread"));
sl@0
   837
	RThread t;
sl@0
   838
	r=t.Create(_L("test7thread"), test7thread, KDefaultStackSize,KHeapSize,KHeapSize,NULL);
sl@0
   839
	test(r==KErrNone);
sl@0
   840
	TRequestStatus stat;
sl@0
   841
	t.Logon(stat);
sl@0
   842
	test.Next(_L("Resume thread"));
sl@0
   843
	t.Resume();
sl@0
   844
	User::After(KWaitTime); // wait a bit;
sl@0
   845
	test.Next(_L("Make thread wait on a semaphore"));
sl@0
   846
	test(progress==EWaiting);
sl@0
   847
	test.Next(_L("Suspend waiting thread"));
sl@0
   848
	t.Suspend();
sl@0
   849
	test.Next(_L("Signal the semaphore"));
sl@0
   850
	gsem.Signal();
sl@0
   851
	User::After(KWaitTime);
sl@0
   852
	test.Next(_L("Test thread still suspended"));
sl@0
   853
	test(progress==EWaiting);
sl@0
   854
	test.Next(_L("resume thread"));
sl@0
   855
	t.Resume();
sl@0
   856
	test.Next(_L("Test the thread no longer waiting on the semaphore"));
sl@0
   857
	User::After(KWaitTime);
sl@0
   858
	test(progress==EDoneWaiting);
sl@0
   859
	test.Next(_L("Wait for thread to finish"));
sl@0
   860
	gsem.Signal();
sl@0
   861
	User::WaitForRequest(stat);
sl@0
   862
	test(stat==KErrNone);
sl@0
   863
	test(progress==EFinished);
sl@0
   864
	CLOSE_AND_WAIT(t);
sl@0
   865
sl@0
   866
	RThread tt;
sl@0
   867
	progress=EBeforeStart;
sl@0
   868
	test.Next(_L("Create Thread"));
sl@0
   869
	r=tt.Create(_L("test7thread"), test7thread, KDefaultStackSize,KHeapSize,KHeapSize,NULL);
sl@0
   870
	test(r==KErrNone);
sl@0
   871
	tt.Logon(stat);
sl@0
   872
	test.Next(_L("Suspend thread without starting it"));
sl@0
   873
	tt.Suspend();
sl@0
   874
	tt.Suspend();
sl@0
   875
	test.Next(_L("Resume and test suspend/resume balance"));
sl@0
   876
	tt.Resume();
sl@0
   877
	tt.Resume();
sl@0
   878
	User::After(KWaitTime);
sl@0
   879
	test(progress==EBeforeStart);
sl@0
   880
	tt.Resume();
sl@0
   881
	test.Next(_L("test thread is suspended on semaphore"));
sl@0
   882
	User::After(KWaitTime);
sl@0
   883
	test(progress==EWaiting);
sl@0
   884
	test.Next(_L("suspend thread"));
sl@0
   885
	tt.Suspend();
sl@0
   886
	tt.Suspend();
sl@0
   887
	test.Next(_L("resume thread"));
sl@0
   888
	tt.Resume();
sl@0
   889
	tt.Resume();
sl@0
   890
	test.Next(_L("test thread still suspended on semaphore"));
sl@0
   891
	User::After(KWaitTime);
sl@0
   892
	test(progress==EWaiting);
sl@0
   893
	test.Next(_L("Suspend, Suspend, Signal semaphore, Suspend"));
sl@0
   894
	tt.Suspend();
sl@0
   895
	tt.Suspend();
sl@0
   896
	gsem.Signal();
sl@0
   897
	tt.Suspend();
sl@0
   898
	test.Next(_L("test thread still suspended on semaphore"));
sl@0
   899
	User::After(KWaitTime);
sl@0
   900
	test(progress==EWaiting);
sl@0
   901
	test.Next(_L("Resume thread, checking suspend/resume balance"));
sl@0
   902
	tt.Resume();
sl@0
   903
	User::After(KWaitTime);
sl@0
   904
	test(progress==EWaiting);
sl@0
   905
	tt.Resume();
sl@0
   906
	User::After(KWaitTime);
sl@0
   907
	test(progress==EWaiting);
sl@0
   908
	tt.Resume();
sl@0
   909
	User::After(KWaitTime);
sl@0
   910
	test(progress==EDoneWaiting);
sl@0
   911
	test.Next(_L("Resume an executing thread"));
sl@0
   912
	tt.Resume();
sl@0
   913
	tt.Resume();
sl@0
   914
//	test.Next(_L("Suspend and check balance"));
sl@0
   915
//	tt.Suspend();
sl@0
   916
//	tt.Suspend();
sl@0
   917
	test.Next(_L("Wait for thread to finish"));
sl@0
   918
	gsem.Signal();
sl@0
   919
	User::After(KWaitTime);
sl@0
   920
	test(progress==EFinished);
sl@0
   921
	User::WaitForRequest(stat);
sl@0
   922
	CLOSE_AND_WAIT(tt);
sl@0
   923
sl@0
   924
//
sl@0
   925
	test.Next(_L("Create Thread"));
sl@0
   926
	r=tt.Create(_L("test7thread"), test7thread, KDefaultStackSize,KHeapSize,KHeapSize,NULL);
sl@0
   927
	test(r==KErrNone);
sl@0
   928
	tt.Logon(stat);
sl@0
   929
	test.Next(_L("Resume"));
sl@0
   930
	tt.Resume();
sl@0
   931
	test.Next(_L("Hang thread on semaphore"));
sl@0
   932
	User::After(KWaitTime);
sl@0
   933
	test(progress==EWaiting);
sl@0
   934
	test.Next(_L("Suspend then Resume thread"));
sl@0
   935
	tt.Suspend();
sl@0
   936
	tt.Suspend();
sl@0
   937
	tt.Resume();
sl@0
   938
	User::After(KWaitTime);
sl@0
   939
	test(progress==EWaiting);
sl@0
   940
	tt.Resume();
sl@0
   941
	test.Next(_L("Check still hanging on semaphore"));
sl@0
   942
	User::After(KWaitTime);
sl@0
   943
	test(progress==EWaiting);
sl@0
   944
	test.Next(_L("Signal Semaphore"));
sl@0
   945
	gsem.Signal();
sl@0
   946
	test.Next(_L("Test thread executing again"));
sl@0
   947
	User::After(KWaitTime);
sl@0
   948
	test(progress==EDoneWaiting);
sl@0
   949
	test.Next(_L("Hang thread on another semaphore, and suspend"));
sl@0
   950
	tt.Suspend();
sl@0
   951
	test.Next(_L("Signal semaphore, and suspend again"));
sl@0
   952
	gsem.Signal();
sl@0
   953
	User::After(KWaitTime);
sl@0
   954
	test(progress==EDoneWaiting);
sl@0
   955
	tt.Suspend();
sl@0
   956
	test.Next(_L("Resume the thread"));
sl@0
   957
	tt.Resume();
sl@0
   958
	User::After(KWaitTime);
sl@0
   959
	test(progress==EDoneWaiting);
sl@0
   960
	tt.Resume();
sl@0
   961
	test.Next(_L("Wait for thread to finish"));
sl@0
   962
	User::After(KWaitTime);
sl@0
   963
	test(progress==EFinished);
sl@0
   964
	User::WaitForRequest(stat);
sl@0
   965
	CLOSE_AND_WAIT(tt);
sl@0
   966
	test.End();
sl@0
   967
	}
sl@0
   968
sl@0
   969
#if 0
sl@0
   970
RSemaphore Sem;
sl@0
   971
LOCAL_D TInt test8thread(TAny* aPtr)
sl@0
   972
//
sl@0
   973
//
sl@0
   974
//
sl@0
   975
	{
sl@0
   976
sl@0
   977
	typedef TBuf<0x20> TTestBuf;
sl@0
   978
	typedef volatile TTestBuf* TTestBufPtr;
sl@0
   979
	volatile TTestBufPtr& pB=*(volatile TTestBufPtr*)aPtr;
sl@0
   980
	if ((TUint)pB != 0xc90fdaa2)
sl@0
   981
		return KErrGeneral;
sl@0
   982
	Sem.Wait();
sl@0
   983
	TDesC* pD=(TDesC*)pB;
sl@0
   984
	test(*pD==_L("Everything's just hunky-dory"));
sl@0
   985
	delete (TTestBufPtr*)pB;
sl@0
   986
	__UHEAP_MARKEND;
sl@0
   987
	return KErrNone;
sl@0
   988
	}
sl@0
   989
#endif
sl@0
   990
sl@0
   991
void test8()
sl@0
   992
//
sl@0
   993
// Get Heap
sl@0
   994
//
sl@0
   995
	{
sl@0
   996
	// !!! RThread::SetInitialParameter no longer exists
sl@0
   997
sl@0
   998
 	/*
sl@0
   999
	typedef TBuf<0x20> TTestBuf;
sl@0
  1000
	TTestBuf* buf=(TTestBuf*)0xc90fdaa2;
sl@0
  1001
sl@0
  1002
	test.Start(_L("Create thread"));
sl@0
  1003
	RThread thread;
sl@0
  1004
	TInt r=thread.Create(_L("test8thread"),test8thread,KDefaultStackSize,KHeapSize,KHeapSize,NULL);
sl@0
  1005
	test(r==KErrNone);
sl@0
  1006
	r=Sem.CreateLocal(0);
sl@0
  1007
	test(r==KErrNone);
sl@0
  1008
	test.Next(_L("Set parameter"));
sl@0
  1009
	r=thread.SetInitialParameter(&buf);
sl@0
  1010
	test(r==KErrNone);
sl@0
  1011
	TRequestStatus stat;
sl@0
  1012
	thread.Logon(stat);
sl@0
  1013
	thread.SetPriority(EPriorityMore);
sl@0
  1014
	test.Next(_L("Resume thread"));
sl@0
  1015
	thread.Resume();
sl@0
  1016
	test.Next(_L("Set initial parameter NULL"));
sl@0
  1017
	r=thread.SetInitialParameter(NULL);
sl@0
  1018
	test(thread.ExitType()==EExitPending);
sl@0
  1019
sl@0
  1020
	test.Next(_L("Get heap"));
sl@0
  1021
	RHeap* heap;
sl@0
  1022
	heap=thread.Heap();
sl@0
  1023
	test.Next(_L("Alloc inside heap"));
sl@0
  1024
	__RHEAP_MARK(heap);
sl@0
  1025
	buf=(TTestBuf*)heap->Alloc(sizeof(TTestBuf));
sl@0
  1026
	test(buf!=NULL);
sl@0
  1027
	new(buf) TTestBuf;
sl@0
  1028
	*buf=(_L("Everything's just hunky-dory"));
sl@0
  1029
sl@0
  1030
	Sem.Signal();
sl@0
  1031
	User::WaitForRequest(stat);
sl@0
  1032
	test(stat==KErrNone);
sl@0
  1033
	test(thread.ExitType()==EExitKill);
sl@0
  1034
	test(thread.ExitReason()==KErrNone);
sl@0
  1035
sl@0
  1036
	test.Next(_L("Close"));
sl@0
  1037
	thread.Close();
sl@0
  1038
	Sem.Close();
sl@0
  1039
	test.End();
sl@0
  1040
	*/
sl@0
  1041
	}
sl@0
  1042
sl@0
  1043
TInt Thread(TAny* /*aAny*/)
sl@0
  1044
	{
sl@0
  1045
sl@0
  1046
	RTest test(_L("Any old thread"));
sl@0
  1047
	test.Next(_L("Find remote thread"));
sl@0
  1048
	// find the main thread
sl@0
  1049
	TFullName name;
sl@0
  1050
	name=RProcess().Name();
sl@0
  1051
	name.Append(_L("::*"));
sl@0
  1052
	TFindThread ft;
sl@0
  1053
	ft.Find(name);
sl@0
  1054
	TInt r=ft.Next(name);
sl@0
  1055
	test(r==KErrNone);
sl@0
  1056
	RThread t;
sl@0
  1057
	t.Open(ft);
sl@0
  1058
sl@0
  1059
	t.Close();
sl@0
  1060
	return KErrNone;
sl@0
  1061
	}
sl@0
  1062
sl@0
  1063
void test9()
sl@0
  1064
	{
sl@0
  1065
sl@0
  1066
	test.Start(_L("Test create a NULL TPtr"));
sl@0
  1067
	TPtr p(NULL, 10, 10);
sl@0
  1068
	test.Next(_L("Create and run remote thread"));
sl@0
  1069
	RThread t;
sl@0
  1070
	TInt r;
sl@0
  1071
	r=t.Create(_L("Any Old Thread"), Thread, 0x2000, 0x2000, 0x2000, (TAny *)&p);
sl@0
  1072
	test(KErrNone==r);
sl@0
  1073
	TRequestStatus stat;
sl@0
  1074
	t.Logon(stat);
sl@0
  1075
	t.Resume();
sl@0
  1076
	test.Next(_L("Wait for thread to complete"));
sl@0
  1077
	User::WaitForRequest(stat);
sl@0
  1078
	test(stat==KErrNone);
sl@0
  1079
	test(t.ExitCategory()==_L("Kill"));
sl@0
  1080
	test(t.ExitReason()==KErrNone);
sl@0
  1081
	test(t.ExitType()==EExitKill);
sl@0
  1082
	CLOSE_AND_WAIT(t);
sl@0
  1083
	test.End();
sl@0
  1084
    }
sl@0
  1085
sl@0
  1086
sl@0
  1087
sl@0
  1088
TInt FoghornLeghorn(TAny* aMutex)
sl@0
  1089
//
sl@0
  1090
// Thread function
sl@0
  1091
//
sl@0
  1092
	{
sl@0
  1093
sl@0
  1094
	((RSemaphore*)aMutex)->Wait();
sl@0
  1095
	RThread thread;
sl@0
  1096
	TInt r=thread.Create(_L("I say * boy"),FoghornLeghorn,KDefaultStackSize,NULL,aMutex);
sl@0
  1097
	test(r==KErrBadName);
sl@0
  1098
	return KErrNone;
sl@0
  1099
	}
sl@0
  1100
sl@0
  1101
void testOpen()
sl@0
  1102
	{
sl@0
  1103
	
sl@0
  1104
	test.Start(_L("Create Foghorn Leghorn"));
sl@0
  1105
	RSemaphore fogMut;
sl@0
  1106
	fogMut.CreateLocal(0);
sl@0
  1107
	RThread foghorn;
sl@0
  1108
	TInt r=foghorn.Create(_L("Foghorn Leghorn"),FoghornLeghorn,KDefaultStackSize,KHeapSize,KHeapSize,&fogMut);
sl@0
  1109
	test(r==KErrNone);
sl@0
  1110
	test.Next(_L("Logon"));
sl@0
  1111
	TRequestStatus stat;
sl@0
  1112
	foghorn.Logon(stat);
sl@0
  1113
	test(stat==KRequestPending);
sl@0
  1114
	test.Next(_L("Resume Foghorn Leghorn"));
sl@0
  1115
	foghorn.Resume();
sl@0
  1116
	test.Next(_L("Get full name"));
sl@0
  1117
	TFindThread find(_L("*Foghorn Leghorn"));
sl@0
  1118
	TFullName name;
sl@0
  1119
	r=find.Next(name);
sl@0
  1120
	test(r==KErrNone);
sl@0
  1121
	test.Next(_L("Open another handle using full name"));
sl@0
  1122
	RThread leghorn;
sl@0
  1123
	r=leghorn.Open(name);
sl@0
  1124
	test(r==KErrNone);
sl@0
  1125
	test.Next(_L("Kill using second handle"));
sl@0
  1126
	leghorn.Kill(34523);
sl@0
  1127
	User::WaitForRequest(stat);
sl@0
  1128
	test(stat==34523);
sl@0
  1129
	test.Next(_L("Close handles"));
sl@0
  1130
	foghorn.Close();
sl@0
  1131
	CLOSE_AND_WAIT(leghorn);
sl@0
  1132
sl@0
  1133
	test.Next(_L("Again! - Create Foghorn Leghorn"));
sl@0
  1134
	r=foghorn.Create(_L("Foghorn Leghorn"),FoghornLeghorn,KDefaultStackSize,KHeapSize,KHeapSize,&fogMut);
sl@0
  1135
	test(r==KErrNone);
sl@0
  1136
	test.Next(_L("Logon"));
sl@0
  1137
	foghorn.Logon(stat);
sl@0
  1138
	test(stat==KRequestPending);
sl@0
  1139
	test.Next(_L("Resume Foghorn Leghorn"));
sl@0
  1140
	foghorn.Resume();
sl@0
  1141
	test.Next(_L("Get full name"));
sl@0
  1142
	find.Find(_L("*Foghorn Leghorn"));
sl@0
  1143
	r=find.Next(name);
sl@0
  1144
	test(r==KErrNone);
sl@0
  1145
	test.Next(_L("Open another handle using full name"));
sl@0
  1146
	r=leghorn.Open(name);
sl@0
  1147
	test(r==KErrNone);
sl@0
  1148
	test.Next(_L("Kill using second handle"));
sl@0
  1149
	leghorn.Kill(67857);
sl@0
  1150
	User::WaitForRequest(stat);
sl@0
  1151
	test(stat==67857);
sl@0
  1152
	test.Next(_L("Close handles"));
sl@0
  1153
	foghorn.Close();
sl@0
  1154
	CLOSE_AND_WAIT(leghorn);
sl@0
  1155
sl@0
  1156
	test.Next(_L("Create Foghorn Leghorn"));
sl@0
  1157
	r=foghorn.Create(_L("Foghorn Leghorn"),FoghornLeghorn,KDefaultStackSize,KHeapSize,KHeapSize,&fogMut);
sl@0
  1158
	test(r==KErrNone);
sl@0
  1159
	test.Next(_L("Logon"));
sl@0
  1160
	foghorn.Logon(stat);
sl@0
  1161
	test(stat==KRequestPending);
sl@0
  1162
	test.Next(_L("Resume Foghorn Leghorn"));
sl@0
  1163
	foghorn.Resume();
sl@0
  1164
	test.Next(_L("Now close it"));
sl@0
  1165
	foghorn.Close();
sl@0
  1166
sl@0
  1167
	test.Next(_L("Get full name"));
sl@0
  1168
	find.Find(_L("*Foghorn Leghorn"));
sl@0
  1169
	r=find.Next(name);
sl@0
  1170
	test(r==KErrNone);
sl@0
  1171
	test.Next(_L("Open using full name"));
sl@0
  1172
	r=leghorn.Open(name);
sl@0
  1173
	test(r==KErrNone);
sl@0
  1174
	test.Next(_L("Kill"));
sl@0
  1175
	leghorn.Kill(67857);
sl@0
  1176
	User::WaitForRequest(stat);
sl@0
  1177
	test(stat==67857);
sl@0
  1178
	test.Next(_L("Close"));
sl@0
  1179
	CLOSE_AND_WAIT(leghorn);
sl@0
  1180
sl@0
  1181
	test.Next(_L("Start and get it to try to start a new thread"));
sl@0
  1182
	r=foghorn.Create(_L("Foghorn Leghorn"),FoghornLeghorn,KDefaultStackSize,KHeapSize,KHeapSize,&fogMut);
sl@0
  1183
	test(r==KErrNone);
sl@0
  1184
	foghorn.Logon(stat);
sl@0
  1185
	test(stat==KRequestPending);
sl@0
  1186
	foghorn.Resume();
sl@0
  1187
	fogMut.Signal();
sl@0
  1188
	User::WaitForRequest(stat);
sl@0
  1189
	test(stat==KErrNone);
sl@0
  1190
	test(foghorn.ExitCategory()==_L("Kill"));
sl@0
  1191
	test(foghorn.ExitReason()==KErrNone);
sl@0
  1192
	test(foghorn.ExitType()==EExitKill);
sl@0
  1193
	test.Next(_L("Close"));
sl@0
  1194
	CLOSE_AND_WAIT(foghorn);
sl@0
  1195
	fogMut.Close();
sl@0
  1196
sl@0
  1197
	test.End();
sl@0
  1198
	}
sl@0
  1199
sl@0
  1200
TInt Bunny(TAny*)
sl@0
  1201
//
sl@0
  1202
// Thread function
sl@0
  1203
//
sl@0
  1204
	{
sl@0
  1205
sl@0
  1206
	FOREVER
sl@0
  1207
		;
sl@0
  1208
	}
sl@0
  1209
sl@0
  1210
void testReuse()
sl@0
  1211
	{
sl@0
  1212
	
sl@0
  1213
	test.Start(_L("Create thread with duplicate name"));
sl@0
  1214
	RThread thread;
sl@0
  1215
	TFullName name=thread.Name();
sl@0
  1216
	TInt r=thread.Create(name,Bunny,KDefaultStackSize,KHeapSize,KHeapSize,NULL);
sl@0
  1217
	test(r==KErrAlreadyExists);
sl@0
  1218
//	thread.Resume(); handle will be invalid since create failed
sl@0
  1219
	test.Next(_L("Create with a good name"));
sl@0
  1220
	r=thread.Create(_L("Bugs Bunny"),Bunny,KDefaultStackSize,KHeapSize,KHeapSize,NULL);
sl@0
  1221
	test(r==KErrNone);
sl@0
  1222
	TRequestStatus stat;
sl@0
  1223
	thread.Logon(stat);
sl@0
  1224
	test.Next(_L("Resume"));
sl@0
  1225
	thread.Resume();
sl@0
  1226
	test.Next(_L("Kill"));
sl@0
  1227
	thread.Kill(15);
sl@0
  1228
	User::WaitForRequest(stat);
sl@0
  1229
	test(stat==15);
sl@0
  1230
	CLOSE_AND_WAIT(thread);
sl@0
  1231
sl@0
  1232
	test.End();
sl@0
  1233
	}
sl@0
  1234
	
sl@0
  1235
sl@0
  1236
TInt HongKongPhooey(TAny * /*aAny*/)
sl@0
  1237
	{
sl@0
  1238
sl@0
  1239
	RMutex m;
sl@0
  1240
	m.OpenGlobal(_L("Test Mutex"));
sl@0
  1241
	m.Wait();
sl@0
  1242
	User::Panic(_L("Hello"),900);
sl@0
  1243
	return KErrNone;
sl@0
  1244
	}
sl@0
  1245
sl@0
  1246
void testReleaseMutex()
sl@0
  1247
//
sl@0
  1248
// Bug HA-187
sl@0
  1249
//
sl@0
  1250
	{
sl@0
  1251
	TInt r;
sl@0
  1252
	test.Start(_L("Create a global Mutex"));
sl@0
  1253
	RMutex m;
sl@0
  1254
	r=m.CreateGlobal(_L("Test Mutex"));
sl@0
  1255
	test.Next(_L("Create a thread"));
sl@0
  1256
	RThread number1SuperGuy;
sl@0
  1257
	r=number1SuperGuy.Create(_L("Hong Kong Phooey"), HongKongPhooey, KDefaultStackSize,KHeapSize,KHeapSize,NULL);
sl@0
  1258
	test(r==KErrNone);
sl@0
  1259
	TRequestStatus s;
sl@0
  1260
	number1SuperGuy.Logon(s);
sl@0
  1261
	test.Next(_L("Resume Thread"));
sl@0
  1262
	number1SuperGuy.Resume();
sl@0
  1263
	test.Next(_L("Wait on Mutex and Panic"));
sl@0
  1264
	User::WaitForRequest(s);
sl@0
  1265
	test(number1SuperGuy.ExitType()==EExitPanic);
sl@0
  1266
	test(number1SuperGuy.ExitCategory()==_L("Hello"));
sl@0
  1267
	test(number1SuperGuy.ExitReason()==900);
sl@0
  1268
	User::After(100000);	// wait a bit for everything to be cleaned up
sl@0
  1269
	m.Wait();
sl@0
  1270
	test.Next(_L("Close everything"));
sl@0
  1271
	m.Close();
sl@0
  1272
	CLOSE_AND_WAIT(number1SuperGuy);
sl@0
  1273
	test.End();
sl@0
  1274
	}
sl@0
  1275
sl@0
  1276
void testId()
sl@0
  1277
	{
sl@0
  1278
sl@0
  1279
	test.Start(_L("Try to open nonexistant thread by ID"));
sl@0
  1280
	RThread thread;
sl@0
  1281
	TInt r=thread.Open(*(TThreadId*)&KMaxTUint);
sl@0
  1282
	test(r==KErrNotFound);
sl@0
  1283
	test.Next(_L("Get thread ID"));
sl@0
  1284
	r=thread.Create(_L("Buster Bunny"),Bunny,KDefaultStackSize,KHeapSize,KHeapSize,NULL);
sl@0
  1285
	test(r==KErrNone);
sl@0
  1286
	TThreadId id=thread.Id();
sl@0
  1287
	TThreadId id2=thread.Id();
sl@0
  1288
	test(id==id2);
sl@0
  1289
	RThread thread2;
sl@0
  1290
	r=thread2.Create(_L("Babs Bunny"),Bunny,KDefaultStackSize,KHeapSize,KHeapSize,NULL);
sl@0
  1291
	test(r==KErrNone);
sl@0
  1292
	id2=thread2.Id();
sl@0
  1293
	test(id!=id2);
sl@0
  1294
	test(*(TUint*)&id+1==*(TUint*)&id2);
sl@0
  1295
	test.Next(_L("Open by ID"));
sl@0
  1296
	TRequestStatus stat;
sl@0
  1297
	thread.Logon(stat);
sl@0
  1298
	thread.Kill(54624);
sl@0
  1299
	User::WaitForRequest(stat);
sl@0
  1300
	test(stat==54624);
sl@0
  1301
	thread.Close();
sl@0
  1302
	r=thread.Open(id2);
sl@0
  1303
	test(r==KErrNone);
sl@0
  1304
	test(thread.Name()==_L("Babs Bunny"));
sl@0
  1305
	test(thread.FullName()==thread2.FullName());
sl@0
  1306
	thread2.Close();
sl@0
  1307
	id=thread.Id();
sl@0
  1308
	test(id==id2);
sl@0
  1309
	thread.Logon(stat);
sl@0
  1310
	thread.Kill(88863);
sl@0
  1311
	User::WaitForRequest(stat);
sl@0
  1312
	test(stat==88863);
sl@0
  1313
	CLOSE_AND_WAIT(thread);
sl@0
  1314
	
sl@0
  1315
	test.End();
sl@0
  1316
	}
sl@0
  1317
sl@0
  1318
struct SCreateInfo
sl@0
  1319
	{
sl@0
  1320
	TInt iStackSize;
sl@0
  1321
	TInt iMinHeapSize;
sl@0
  1322
	TInt iMaxHeapSize;
sl@0
  1323
	};
sl@0
  1324
sl@0
  1325
TInt BadCreation(TAny* aCreateInfo)
sl@0
  1326
	{
sl@0
  1327
	SCreateInfo& info=*((SCreateInfo*)aCreateInfo);
sl@0
  1328
	RThread thread;
sl@0
  1329
	thread.Create(_L("Won't work"),Bunny,info.iStackSize,info.iMinHeapSize,info.iMaxHeapSize,NULL);
sl@0
  1330
	return KErrNone;
sl@0
  1331
	}
sl@0
  1332
sl@0
  1333
void testCreate()
sl@0
  1334
	{
sl@0
  1335
	test.Start(_L("Negative stack size"));
sl@0
  1336
	RThread thread;
sl@0
  1337
	TRequestStatus stat;
sl@0
  1338
	TInt r;
sl@0
  1339
	{
sl@0
  1340
	SCreateInfo info={-1,0x1000,0x1000};
sl@0
  1341
	r=thread.Create(_L("Test Create"),BadCreation,KDefaultStackSize,KHeapSize,KHeapSize,&info);
sl@0
  1342
	test(KErrNone==r);
sl@0
  1343
	thread.Logon(stat);
sl@0
  1344
	thread.Resume();
sl@0
  1345
	User::WaitForRequest(stat);
sl@0
  1346
	test(stat==EThrdStackSizeNegative);
sl@0
  1347
	test(thread.ExitType()==EExitPanic);
sl@0
  1348
	test(thread.ExitReason()==EThrdStackSizeNegative);
sl@0
  1349
	test(thread.ExitCategory()==_L("USER"));
sl@0
  1350
	CLOSE_AND_WAIT(thread);
sl@0
  1351
	}
sl@0
  1352
//
sl@0
  1353
	test.Next(_L("Negative heap min size"));
sl@0
  1354
	{
sl@0
  1355
	SCreateInfo info={0x1000,-1,0x1000};
sl@0
  1356
	r=thread.Create(_L("Test Create"),BadCreation,KDefaultStackSize,KHeapSize,KHeapSize,&info);
sl@0
  1357
	test(KErrNone==r);
sl@0
  1358
	thread.Logon(stat);
sl@0
  1359
	thread.Resume();
sl@0
  1360
	User::WaitForRequest(stat);
sl@0
  1361
	test(stat==EThrdHeapMinTooSmall);
sl@0
  1362
	test(thread.ExitType()==EExitPanic);
sl@0
  1363
	test(thread.ExitReason()==EThrdHeapMinTooSmall);
sl@0
  1364
	test(thread.ExitCategory()==_L("USER"));
sl@0
  1365
	CLOSE_AND_WAIT(thread);
sl@0
  1366
	}
sl@0
  1367
	test.Next(_L("Negative heap max size"));
sl@0
  1368
	{
sl@0
  1369
	SCreateInfo info={0x1000,0x1000,-1};
sl@0
  1370
	r=thread.Create(_L("Test Create"),BadCreation,KDefaultStackSize,KHeapSize,KHeapSize,&info);
sl@0
  1371
	test(KErrNone==r);
sl@0
  1372
	thread.Logon(stat);
sl@0
  1373
	thread.Resume();
sl@0
  1374
	User::WaitForRequest(stat);
sl@0
  1375
	test(stat==EThrdHeapMaxLessThanMin);
sl@0
  1376
	test(thread.ExitType()==EExitPanic);
sl@0
  1377
	test(thread.ExitReason()==EThrdHeapMaxLessThanMin);
sl@0
  1378
	test(thread.ExitCategory()==_L("USER"));
sl@0
  1379
	CLOSE_AND_WAIT(thread);
sl@0
  1380
	}
sl@0
  1381
	test.Next(_L("heap max size < heap min size"));
sl@0
  1382
	{
sl@0
  1383
	SCreateInfo info={0x1000,0x2001,0x1000};
sl@0
  1384
	r=thread.Create(_L("Test Create"),BadCreation,KDefaultStackSize,KHeapSize,KHeapSize,&info);
sl@0
  1385
	test(KErrNone==r);
sl@0
  1386
	thread.Logon(stat);
sl@0
  1387
	thread.Resume();
sl@0
  1388
	User::WaitForRequest(stat);
sl@0
  1389
	test(stat==EThrdHeapMaxLessThanMin);
sl@0
  1390
	test(thread.ExitType()==EExitPanic);
sl@0
  1391
	test(thread.ExitReason()==EThrdHeapMaxLessThanMin);
sl@0
  1392
	test(thread.ExitCategory()==_L("USER"));
sl@0
  1393
	CLOSE_AND_WAIT(thread);
sl@0
  1394
	}
sl@0
  1395
	test.Next(_L("Little min heap size"));
sl@0
  1396
	{
sl@0
  1397
	SCreateInfo info={0x1000,KMinHeapSize-1,0x1000};
sl@0
  1398
	r=thread.Create(_L("Test Create"),BadCreation,KDefaultStackSize,KHeapSize,KHeapSize,&info);
sl@0
  1399
	test(KErrNone==r);
sl@0
  1400
	thread.Logon(stat);
sl@0
  1401
	thread.Resume();
sl@0
  1402
	User::WaitForRequest(stat);
sl@0
  1403
	test(stat==EThrdHeapMinTooSmall);
sl@0
  1404
	test(thread.ExitType()==EExitPanic);
sl@0
  1405
	test(thread.ExitReason()==EThrdHeapMinTooSmall);
sl@0
  1406
	test(thread.ExitCategory()==_L("USER"));
sl@0
  1407
	CLOSE_AND_WAIT(thread);
sl@0
  1408
	}
sl@0
  1409
	test.End();
sl@0
  1410
	}
sl@0
  1411
sl@0
  1412
TInt StackInfoThread(TAny*)
sl@0
  1413
	{
sl@0
  1414
	TInt a;
sl@0
  1415
	RThread::Rendezvous((TInt)&a);  // Complete rendezvous using address of 'a' which is on the stack
sl@0
  1416
	return 0;
sl@0
  1417
	}
sl@0
  1418
sl@0
  1419
void testThreadStackInfo()
sl@0
  1420
	{
sl@0
  1421
	// Check the info about the current thread's stack
sl@0
  1422
	RThread thread;
sl@0
  1423
	TThreadStackInfo info;
sl@0
  1424
	TInt r = thread.StackInfo(info);
sl@0
  1425
	test(r==KErrNone);
sl@0
  1426
	TLinAddr a = (TLinAddr)&info;
sl@0
  1427
	test.Printf(_L("address on stack=%x iBase=%x iLimit=%x iExpandLimit=%x"),a,info.iBase,info.iLimit,info.iExpandLimit);
sl@0
  1428
	test(a<=info.iBase);
sl@0
  1429
	test(a>=info.iLimit);
sl@0
  1430
	test(info.iExpandLimit<=info.iLimit);
sl@0
  1431
sl@0
  1432
	// Create another thread
sl@0
  1433
	r=thread.Create(_L("StackInfoThread"),StackInfoThread,KDefaultStackSize,KHeapSize,KHeapSize,(TAny*)NULL);
sl@0
  1434
	test(r==KErrNone);
sl@0
  1435
	thread.SetPriority(EPriorityLess);
sl@0
  1436
sl@0
  1437
	// Resume thread and wait for it to run
sl@0
  1438
	TRequestStatus stat;
sl@0
  1439
	thread.Rendezvous(stat);
sl@0
  1440
	thread.Resume();
sl@0
  1441
	User::WaitForRequest(stat);
sl@0
  1442
sl@0
  1443
	// Test getting stack info of another thread
sl@0
  1444
	r = thread.StackInfo(info);
sl@0
  1445
	test(r==KErrNone);
sl@0
  1446
	a = stat.Int(); // a = an address on the threads stack
sl@0
  1447
	test.Printf(_L("address on stack=%x iBase=%x iLimit=%x iExpandLimit=%x"),a,info.iBase,info.iLimit,info.iExpandLimit);
sl@0
  1448
	test(a<=info.iBase);
sl@0
  1449
	test(a>=info.iLimit);
sl@0
  1450
	test(info.iExpandLimit<=info.iLimit);
sl@0
  1451
sl@0
  1452
	// Let thread run to end
sl@0
  1453
	thread.Logon(stat);
sl@0
  1454
	User::WaitForRequest(stat);
sl@0
  1455
	test(stat.Int()==0);
sl@0
  1456
	}
sl@0
  1457
sl@0
  1458
GLDEF_C TInt E32Main()
sl@0
  1459
//
sl@0
  1460
// Main
sl@0
  1461
//
sl@0
  1462
	{	
sl@0
  1463
 
sl@0
  1464
	// don't want just in time debugging as we trap panics
sl@0
  1465
	TBool justInTime=User::JustInTime(); 
sl@0
  1466
	User::SetJustInTime(EFalse); 
sl@0
  1467
sl@0
  1468
	test.Title();
sl@0
  1469
	__UHEAP_MARK;
sl@0
  1470
	
sl@0
  1471
sl@0
  1472
	TFullName name;
sl@0
  1473
	name=RThread().Name();
sl@0
  1474
sl@0
  1475
	test.Start(_L("Test threads"));
sl@0
  1476
sl@0
  1477
	test.Next(_L("Test 1"));
sl@0
  1478
	test1();
sl@0
  1479
 
sl@0
  1480
	test.Next(_L("Test create"));
sl@0
  1481
	testCreate();
sl@0
  1482
sl@0
  1483
	test.Next(_L("Test RUndertaker"));
sl@0
  1484
	testUndertaker(EOwnerProcess);
sl@0
  1485
sl@0
  1486
	test.Next(_L("Test2"));
sl@0
  1487
	test2(EOwnerProcess);
sl@0
  1488
	User::SetJustInTime(justInTime);	
sl@0
  1489
	test.Next(_L("Test3"));
sl@0
  1490
	test3();
sl@0
  1491
	test.Next(_L("Test4"));
sl@0
  1492
	test4();
sl@0
  1493
	test.Next(_L("Completed but unclosed thread"));
sl@0
  1494
	User::SetJustInTime(EFalse);
sl@0
  1495
	test5();
sl@0
  1496
	User::SetJustInTime(justInTime);
sl@0
  1497
	test.Next(_L("Suspend/Resume"));
sl@0
  1498
	test7();
sl@0
  1499
	test.Next(_L("Testing thread duplication"));
sl@0
  1500
	User::SetJustInTime(EFalse);
sl@0
  1501
	test6();
sl@0
  1502
	User::SetJustInTime(justInTime);
sl@0
  1503
	test.Next(_L("Get thread's heap"));
sl@0
  1504
	test8();
sl@0
  1505
	test.Next(_L("Test read NULL remotely (HA-178)"));
sl@0
  1506
	test9();
sl@0
  1507
	test.Next(_L("Test Open(aFullName)"));
sl@0
  1508
	testOpen();
sl@0
  1509
	test.Next(_L("Test Reuse after a failed create"));
sl@0
  1510
	testReuse();
sl@0
  1511
	test.Next(_L("Test thread releases Mutex (HA-178)"));
sl@0
  1512
	User::SetJustInTime(EFalse);
sl@0
  1513
	testReleaseMutex();
sl@0
  1514
	User::SetJustInTime(justInTime);
sl@0
  1515
	test.Next(_L("Test Thread ID"));
sl@0
  1516
	testId();
sl@0
  1517
	test.Next(_L("Test RThread::StackInfo"));
sl@0
  1518
	testThreadStackInfo();
sl@0
  1519
	test.End();
sl@0
  1520
	__UHEAP_MARKEND;
sl@0
  1521
	return(KErrNone);
sl@0
  1522
	}
sl@0
  1523
sl@0
  1524
sl@0
  1525