os/kernelhwsrv/kerneltest/e32test/mqueue/t_mqueue.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     4 // under the terms of the License "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 // e32test\mqueue\t_mqueue.cpp
    15 // Overview:
    16 // Test message queuing
    17 // API Information:
    18 // RMsgQueue, RMsgQueueBase
    19 // Details:
    20 // - Create various illegal and legal private message queues and verify 
    21 // results are as expected. Test private message queue functionality in
    22 // both single threaded tests and multi-threaded tests.
    23 // - Create various illegal and legal global named message queues and verify 
    24 // results are as expected. Test global named message queue functionality
    25 // in both single threaded tests and multi-threaded tests.
    26 // - Test multi-process queues and template based queues, verify results are 
    27 // as expected.
    28 // Platforms/Drives/Compatibility:
    29 // All.
    30 // Assumptions/Requirement/Pre-requisites:
    31 // Failures and causes:
    32 // Base Port information:
    33 // 
    34 //
    35 
    36 #include <e32test.h>
    37 #include <e32svr.h>
    38 #include <e32msgqueue.h>
    39 #include <f32file.h>
    40 
    41 LOCAL_D RTest test(_L("t_mqueue"));
    42 
    43 //if the test is to run under the debugger, uncomment the following line
    44 //#define _DEBUGGER_BUILD
    45 
    46 const TInt KHeapSize=0x2000;
    47 const TInt KTestValue = 42;
    48 _LIT8(KFillPattern, "1234567890");
    49 
    50 _LIT(KGLobalName1, "GlobalMessageQueue1");
    51 
    52 
    53 LOCAL_C void SingleThreadedTests(RMsgQueueBase& aQueue, TInt aSlots, TInt aSize)
    54 	{
    55 	test.Printf(_L("Single Threaded Tests"));
    56 
    57 
    58 	TRequestStatus stat;
    59 	test.Next(_L("test CancelDataAvailable"));
    60 	aQueue.NotifyDataAvailable(stat);
    61 	test (stat == KRequestPending);
    62 	aQueue.CancelDataAvailable();
    63 	User::WaitForRequest(stat);
    64 	test (stat == KErrCancel);
    65 
    66 	TUint8 * pSourceData = (TUint8*)User::Alloc(aSize*2);
    67 	test(pSourceData != NULL);	
    68 	TPtr8 pS(pSourceData, aSize*2, aSize*2);
    69 	pS.Repeat(KFillPattern);
    70 
    71 	TUint8 * pDestinationData = (TUint8*)User::Alloc(aSize*2);
    72 	test(pDestinationData != NULL);
    73 	TPtr8 pD(pDestinationData, aSize*2, aSize*2);
    74 	pD.FillZ();
    75 
    76 
    77 	test.Next(_L("test MessageSize"));
    78 	test(aQueue.MessageSize() == aSize);
    79 
    80 
    81 	test.Next(_L("Send a legal message through"));
    82 	TInt ret = aQueue.Send(pSourceData, aSize);
    83 	test(ret == KErrNone);
    84 
    85 	test.Next(_L("Receive legal message"));
    86 	ret = aQueue.Receive(pDestinationData, aSize);
    87 	test(ret == KErrNone);
    88 	TPtr8 p(pS);
    89 	p.SetLength(aSize);
    90 	pD.SetLength(aSize);
    91 	test(p == pD);
    92 	pD.FillZ();
    93 
    94 	test.Next(_L("Send a short message through"));
    95 	ret = aQueue.Send(pSourceData, aSize/2);
    96 	test(ret == KErrNone);
    97 
    98 	test.Next(_L("Receive legal message"));
    99 	ret = aQueue.Receive(pDestinationData, aSize);
   100 	test(ret == KErrNone);
   101 	p.SetLength(aSize/2);
   102 	pD.SetLength(aSize/2);
   103 	test(p == pD);
   104 	pD.FillZ();
   105 
   106 	test.Next(_L("Test Receive with no message"));
   107 	ret = aQueue.Receive(pDestinationData, aSize);
   108 	test(ret == KErrUnderflow);
   109 
   110 	if (aSlots >= 2)
   111 		{	
   112 		test.Next(_L("Send two legal messages through"));
   113 		pS[0] = 0;
   114 		ret = aQueue.Send(pSourceData, aSize);
   115 		test(ret == KErrNone);
   116 		pS[0] = 1;
   117 		ret = aQueue.Send(pSourceData, aSize);
   118 		test(ret == KErrNone);
   119 
   120 		test.Next(_L("Receive two legal messages in tx order"));
   121 		ret = aQueue.Receive(pDestinationData, aSize);
   122 		test(ret == KErrNone);
   123 		test(pD[0] == 0);
   124 		pD.FillZ();
   125 		ret = aQueue.Receive(pDestinationData, aSize);
   126 		test(ret == KErrNone);
   127 		test(pD[0] == 1);
   128 		pD.FillZ();
   129 
   130 		}
   131 	
   132 	test.Next(_L("Test filling the queue to the max"));
   133 	TInt x;
   134 	for (x = 0; x < aSlots; x++)
   135 		{
   136 		pS[0] = (TUint8)x;
   137 		ret = aQueue.Send(pSourceData, aSize);
   138 		test(ret == KErrNone);
   139 		}
   140 
   141 	test.Next(_L("Test one too many sends"));
   142 	ret = aQueue.Send(pSourceData, aSize);
   143 	test(ret == KErrOverflow);
   144 
   145 	test.Next(_L("test cancel SpaceAvailable"));
   146 	aQueue.NotifySpaceAvailable(stat);
   147 	test (stat == KRequestPending);
   148 	aQueue.CancelSpaceAvailable();
   149 	User::WaitForRequest(stat);
   150 	test (stat == KErrCancel);
   151 
   152 
   153 	test.Next(_L("Test emptying the queue"));
   154 
   155 	for (x = 0; x < aSlots; x++)
   156 		{
   157 		ret = aQueue.Receive(pDestinationData, aSize);
   158 		test(ret == KErrNone);
   159 		test(pD[0] == (TUint8)x );
   160 		pD.FillZ();
   161 		}
   162 
   163 	test.Next(_L("test cancel DataAvailable"));
   164 	aQueue.NotifyDataAvailable(stat);
   165 	test (stat == KRequestPending);
   166 	aQueue.CancelDataAvailable();
   167 	User::WaitForRequest(stat);
   168 	test (stat == KErrCancel);
   169 
   170 	test.Next(_L("Test one too many receives"));
   171 	ret = aQueue.Receive(pDestinationData, aSize);
   172 	test(ret == KErrUnderflow);
   173 
   174 
   175 	test.Next(_L("Test wrap around"));
   176 	test.Printf(_L("fill queue to max\n"));
   177 	for (x = 0; x < aSlots; x++)
   178 		{
   179 		pS[0] = (TUint8)x;
   180 		ret = aQueue.Send(pSourceData, aSize);
   181 		test(ret == KErrNone);
   182 		}
   183 
   184 	test.Printf(_L("half empty the queue\n"));
   185 	for (x = 0; x < aSlots/2; x++)
   186 		{
   187 		ret = aQueue.Receive(pDestinationData, aSize);
   188 		test(ret == KErrNone);
   189 		test(pD[0] == (TUint8)x);
   190 		pD.FillZ();
   191 		}
   192 
   193 	test.Printf(_L("fill queue to max\n"));
   194 	for (x = 0; x < aSlots/2; x++)
   195 		{
   196 		pS[0] = (TUint8)x;
   197 		ret = aQueue.Send(pSourceData, aSize);
   198 		test (ret == KErrNone);
   199 		}
   200 		ret = aQueue.Send(pSourceData, aSize);
   201 		test (ret == KErrOverflow);
   202 
   203 	test.Printf(_L("empty the queue\n"));
   204 	for (x = aSlots/2; x < aSlots; x++)
   205 		{
   206 		ret = aQueue.Receive(pDestinationData, aSize);
   207 		test(ret == KErrNone);
   208 		test(pD[0] == (TUint8)x);
   209 		}
   210 	for (x = 0; x < aSlots/2; x++)
   211 		{
   212 		ret = aQueue.Receive(pDestinationData, aSize);
   213 		test(ret == KErrNone);
   214 		test(pD[0] == (TUint8)x);
   215 		}
   216 
   217 	test.Next(_L("Test queue is empty"));
   218 	ret = aQueue.Receive(pDestinationData, aSize);
   219 	test(ret == KErrUnderflow);
   220 
   221 	User::Free(pSourceData);
   222 	User::Free(pDestinationData);
   223 	}
   224 
   225 
   226 _LIT(KThread2Name, "thread2");
   227 _LIT(KThread3Name, "thread3");
   228 _LIT(KThread4Name, "thread4");
   229 
   230 
   231 class TData 
   232 	{
   233 public:
   234 	TData(RMsgQueueBase* aQ, TInt aSize, TInt aSlots,TInt aTest=0, TAny* aData=NULL);
   235 	RMsgQueueBase* iQueue;
   236 	TInt iSize;
   237 	TInt iSlots;
   238 	TInt iTest;
   239 	TAny* iData;
   240 	};
   241 
   242 TData::TData(RMsgQueueBase* aQ, TInt aSize, TInt aSlots, TInt aTest, TAny* aData) :	iQueue(aQ), iSize(aSize),
   243 																		iSlots(aSlots), iTest(aTest), iData(aData)
   244 	{
   245 	//empty
   246 	};
   247 
   248 
   249 
   250 LOCAL_C TInt illegalSendEntryPoint(TAny* aData)
   251 	{
   252 	
   253 	TData& data = *(TData *)aData;
   254 
   255 	switch (data.iTest)
   256 		{
   257 	case 0:
   258 		data.iQueue->Send(data.iData, data.iSize*2);	//should panic, message size incorrect
   259 		break;
   260 
   261 	case 1:
   262 #ifdef _DEBUGGER_BUILD
   263 		#pragma message ("BUILT FOR DEBUGGER")
   264 		User::Panic(_L("test"),ECausedException);
   265 #else
   266 		data.iQueue->Send((TAny*)0xfeed, data.iSize);	//should panic
   267 #endif
   268 	break;
   269 
   270 	case 2:
   271 #ifdef _DEBUGGER_BUILD
   272 		#pragma message ("BUILT FOR DEBUGGER")
   273 		User::Panic(_L("test"),ECausedException);
   274 #else
   275 		data.iQueue->Send((TAny*)0xDEDEDEDE, data.iSize);	//dodgy address
   276 #endif	
   277 		break;
   278 		}
   279 
   280 	test(0);	//should never get here.  This'll make a Kern Exec 0! as tries to use console from different thread
   281 	return 0;
   282 	}
   283 
   284 
   285 LOCAL_C TInt illegalReceiveEntryPoint(TAny* aData)
   286 	{
   287 	
   288 	TData& data = *(TData *)aData;
   289 	TUint8 buf[256];
   290 
   291 	switch (data.iTest)
   292 		{
   293 	case 0:
   294 		data.iQueue->Receive(buf, data.iSize*2);	//should panic, message size incorrect
   295 		break;
   296 
   297 	case 1:
   298 #ifdef _DEBUGGER_BUILD
   299 		#pragma message ("BUILT FOR DEBUGGER")
   300 		User::Panic(_L("test"),ECausedException);
   301 #else
   302 		data.iQueue->Receive((TAny*)0xfeed, data.iSize);	//should panic
   303 #endif
   304 		break;
   305 
   306 	case 2:
   307 #ifdef _DEBUGGER_BUILD
   308 		#pragma message ("BUILT FOR DEBUGGER")
   309 		User::Panic(_L("test"),ECausedException);
   310 #else
   311 		data.iQueue->Receive((TAny*)0xDEDEDEDE, data.iSize);	//dodgy address
   312 #endif
   313 		break;
   314 
   315 		}
   316 
   317 	test(0);	//should never get here.  This'll make a Kern Exec 0!
   318 	return 0;
   319 	}
   320 
   321 
   322 
   323 LOCAL_C TInt sendBlockingEntryPoint(TAny* aData)
   324 	{
   325 	TData& data = *(TData *)aData;
   326 
   327 	TInt d = KTestValue;
   328 	data.iQueue->SendBlocking(&d, 4);
   329 	return KErrNone;
   330 	}
   331 
   332 LOCAL_C TInt receiveBlockingEntryPoint(TAny* aData)
   333 	{
   334 	TData& data = *(TData *)aData;
   335 
   336 	TUint8  pData[256];
   337 	TPtr8 pD(pData, data.iSize, data.iSize);
   338 	pD.FillZ();
   339 	data.iQueue->ReceiveBlocking(pData, data.iSize);
   340 	test (*(TInt*)pData == KTestValue);
   341 	return KErrNone;
   342 	}
   343 
   344 
   345 LOCAL_C TInt notifyDataAvailableEntryPoint(TAny* aData)
   346 	{
   347 	TData& data = *(TData *)aData;
   348 
   349 	//check size as well
   350 	test(data.iQueue->MessageSize() == data.iSize);
   351 
   352 	TRequestStatus stat;
   353 	data.iQueue->NotifyDataAvailable(stat);
   354 	User::WaitForRequest(stat);
   355 	return KErrNone;
   356 	}
   357 
   358 LOCAL_C TInt notifySpaceAvailableEntryPoint(TAny* aData)
   359 	{
   360 	TData& data = *(TData *)aData;
   361 
   362 	TRequestStatus stat;
   363 	data.iQueue->NotifySpaceAvailable(stat);
   364 	User::WaitForRequest(stat);
   365 	return KErrNone;
   366 	}
   367 
   368 
   369 
   370 LOCAL_C void MultiThreadedTests(RMsgQueueBase& aQueue, TInt aSlots, TInt aSize)
   371 	{
   372 	test.Next(_L("multi threaded tests"));
   373 	RThread thread2;
   374 	TInt ret = KErrNone;
   375 
   376 	TAny* ptr = User::Alloc(aSize);
   377 
   378 	test.Next(_L("test Send with illegal parameters"));
   379 	TInt testnum;
   380 	TBool jit = User::JustInTime();
   381 	User::SetJustInTime(EFalse);
   382 	for (testnum = 0; testnum < 3; testnum++)	//testnum range is determined by the number of tests in illegalSendEntryPoint
   383 		{
   384 		TData data(&aQueue, aSize, aSlots, testnum, ptr);
   385 		ret = thread2.Create(KThread2Name, illegalSendEntryPoint, KDefaultStackSize, KHeapSize, KHeapSize, &data);
   386 		test(KErrNone == ret);
   387 		TRequestStatus thread2stat;
   388 		thread2.Logon(thread2stat);
   389 		thread2.Resume();
   390 		User::WaitForRequest(thread2stat);
   391 		test (thread2.ExitType() == EExitPanic);
   392 		switch (testnum)
   393 		{
   394 		case 0:
   395 		test (thread2.ExitReason() == EMsgQueueInvalidLength);
   396 		break;
   397 		case 1:
   398 		test (thread2.ExitReason() == ECausedException);
   399 		break;
   400 		case 2:
   401 		test (thread2.ExitReason() == ECausedException);
   402 		break;
   403 		}
   404 
   405 		CLOSE_AND_WAIT(thread2);
   406 		}
   407 
   408 	
   409 	User::SetJustInTime(jit);
   410 
   411 	
   412 	test.Next(_L("test Receive with illegal parameters"));
   413 	jit = User::JustInTime();
   414 	User::SetJustInTime(EFalse);
   415 
   416 
   417 	for (testnum = 0; testnum < 3; testnum++)	//testnum range is determined by the number of tests in illegalReceiveEntryPoint
   418 		{
   419 	//put something in the queue
   420 		aQueue.Send(&testnum, 4);
   421 		TData data(&aQueue, aSize, aSlots, testnum, ptr);
   422 		ret = thread2.Create(KThread2Name, illegalReceiveEntryPoint, KDefaultStackSize, KHeapSize, KHeapSize, &data);
   423 		test(KErrNone == ret);
   424 		TRequestStatus thread2stat;
   425 		thread2.Logon(thread2stat);
   426 		thread2.Resume();
   427 		User::WaitForRequest(thread2stat);
   428 		test (thread2.ExitType() == EExitPanic);
   429 		
   430 		switch (testnum)
   431 		{
   432 		case 0:
   433 		test (thread2.ExitReason() == EMsgQueueInvalidLength);
   434 		break;
   435 		case 1:
   436 		test (thread2.ExitReason() == ECausedException);
   437 		break;
   438 		case 2:
   439 		test (thread2.ExitReason() == ECausedException);
   440 		break;
   441 		}
   442 
   443 		CLOSE_AND_WAIT(thread2);
   444 		}
   445 
   446 	
   447 	User::SetJustInTime(jit);
   448 
   449 	while(KErrNone == aQueue.Receive(ptr, aSize))	//empty the queue
   450 		{
   451 		//empty,
   452 		}
   453 	
   454 	test.Next(_L("multi threaded NotifySpaceAvailable"));
   455 
   456 	TInt dummydata = KTestValue;
   457 	//fill the queue
   458 	while (KErrNone == aQueue.Send(&dummydata, sizeof (TInt)))
   459 		{
   460 		//empty
   461 		}
   462 
   463 	TData data(&aQueue, aSize, aSlots);
   464 	ret = thread2.Create(KThread2Name, notifySpaceAvailableEntryPoint, KDefaultStackSize, KHeapSize, KHeapSize, &data);
   465 	test(KErrNone == ret);
   466 	TRequestStatus thread2stat;
   467 	thread2.Logon(thread2stat);
   468 	thread2.Resume();
   469 
   470 	//thread2 should be waiting for space available
   471 	test (thread2stat == KRequestPending);
   472 	aQueue.ReceiveBlocking(ptr, aSize);
   473 	User::WaitForRequest(thread2stat);
   474 	test (thread2stat == KErrNone);
   475 	test (thread2.ExitType() == EExitKill);
   476 	CLOSE_AND_WAIT(thread2);
   477 	//thread 2 has exited OK
   478 
   479 	//empty the queue
   480 	while (KErrNone == aQueue.Receive(ptr, aSize))
   481 		{
   482 		//empty
   483 		}
   484 
   485 	
   486 	test.Next(_L("multi threaded SendBlocking, ReceiveBlocking"));
   487 	ret = thread2.Create(KThread2Name, receiveBlockingEntryPoint, KDefaultStackSize, KHeapSize, KHeapSize, &data);
   488 	test(KErrNone == ret);
   489 	thread2.Logon(thread2stat);
   490 	thread2.Resume();
   491 
   492 	aQueue.SendBlocking(&dummydata, sizeof (TInt));
   493 
   494 	User::WaitForRequest(thread2stat);
   495 	test (thread2.ExitType() == EExitKill);
   496 	CLOSE_AND_WAIT(thread2);
   497 
   498 
   499 	test.Next(_L("multiple ReceiveBlocking"));
   500 	ret = thread2.Create(KThread2Name, receiveBlockingEntryPoint, KDefaultStackSize, KHeapSize, KHeapSize, &data);
   501 	test(KErrNone == ret);
   502 
   503 	RThread thread3;
   504 	ret = thread3.Create(KThread3Name, receiveBlockingEntryPoint, KDefaultStackSize, KHeapSize, KHeapSize, &data);
   505 	test(KErrNone == ret);
   506 
   507 	RThread thread4;
   508 	ret = thread4.Create(KThread4Name, receiveBlockingEntryPoint, KDefaultStackSize, KHeapSize, KHeapSize, &data);
   509 	test(KErrNone == ret);
   510 
   511 	thread2.Logon(thread2stat);
   512 
   513 	TRequestStatus thread3stat;
   514 	thread3.Logon(thread3stat);
   515 	
   516 	TRequestStatus thread4stat;
   517 	thread4.Logon(thread4stat);
   518 
   519 	thread2.Resume();
   520 	User::After(500000);
   521 
   522 	jit = User::JustInTime();
   523 	User::SetJustInTime(EFalse);
   524 
   525 	thread3.Resume();
   526 	thread4.Resume();
   527 
   528 	
   529 	User::WaitForRequest(thread3stat, thread4stat);
   530 	if (thread3stat != KRequestPending)
   531 		User::WaitForRequest(thread4stat);
   532 	else
   533 		User::WaitForRequest(thread3stat);
   534 	User::SetJustInTime(jit);
   535 
   536 	//threads 3 and 4 have exited
   537 	test (thread3.ExitType() == EExitPanic);
   538 	test (thread3.ExitReason() == EMsgQueueRequestPending);
   539 	test (thread4.ExitType() == EExitPanic);
   540 	test (thread4.ExitReason() == EMsgQueueRequestPending);
   541 	
   542 	test (thread2stat == KRequestPending);
   543 	aQueue.SendBlocking(&dummydata, sizeof (TInt));
   544 	User::WaitForRequest(thread2stat);
   545 	test (thread2stat == KErrNone);
   546 	test (thread2.ExitType() == EExitKill);
   547 
   548 	CLOSE_AND_WAIT(thread2);
   549 	CLOSE_AND_WAIT(thread3);
   550 	CLOSE_AND_WAIT(thread4);
   551 
   552 
   553 	//fill the queue
   554 	while (KErrNone == aQueue.Send(&dummydata, sizeof (TInt)))
   555 		{
   556 		//empty
   557 		}
   558 
   559 	test.Next(_L("multiple sendblocking"));
   560 	ret = thread2.Create(KThread2Name, sendBlockingEntryPoint, KDefaultStackSize, KHeapSize, KHeapSize, &data);
   561 	test(KErrNone == ret);
   562 	ret = thread3.Create(KThread3Name, sendBlockingEntryPoint, KDefaultStackSize, KHeapSize, KHeapSize, &data);
   563 	test(KErrNone == ret);
   564 	ret = thread4.Create(KThread4Name, sendBlockingEntryPoint, KDefaultStackSize, KHeapSize, KHeapSize, &data);
   565 	test(KErrNone == ret);
   566 
   567 	thread2.Logon(thread2stat);
   568 	thread3.Logon(thread3stat);
   569 	thread4.Logon(thread4stat);
   570 
   571 	thread2.Resume();
   572 	User::After(500000);
   573 
   574 	jit = User::JustInTime();
   575 	User::SetJustInTime(EFalse);
   576 	thread3.Resume();
   577 	thread4.Resume();
   578 	User::WaitForRequest(thread3stat, thread4stat);
   579 	if (thread3stat != KRequestPending)
   580 		User::WaitForRequest(thread4stat);
   581 	else
   582 		User::WaitForRequest(thread3stat);
   583 	User::SetJustInTime(jit);
   584 
   585 	//threads 3 and 4 have exited
   586 	test (thread3.ExitType() == EExitPanic);
   587 	test (thread3.ExitReason() == EMsgQueueRequestPending);
   588 	test (thread4.ExitType() == EExitPanic);
   589 	test (thread4.ExitReason() == EMsgQueueRequestPending);
   590 	
   591 	test (thread2stat == KRequestPending);
   592 
   593 	//consume one to allow the blocking write
   594 	test(KErrNone == aQueue.Receive(ptr, aSize));
   595 
   596 	User::WaitForRequest(thread2stat);
   597 	test (thread2stat == KErrNone);
   598 	test (thread2.ExitType() == EExitKill);
   599 
   600 	//consume the rest of the queue
   601 	while (KErrNone == aQueue.Receive(ptr, aSize))
   602 		{
   603 		// empty
   604 		}
   605 
   606 	CLOSE_AND_WAIT(thread2);
   607 	CLOSE_AND_WAIT(thread3);
   608 	CLOSE_AND_WAIT(thread4);
   609 
   610 	
   611 	test.Next(_L("multi threaded NotifyDataAvailable"));
   612 	ret = thread2.Create(KThread2Name, notifyDataAvailableEntryPoint, KDefaultStackSize, KHeapSize, KHeapSize, &data);
   613 	test(KErrNone == ret);
   614 	thread2.Logon(thread2stat);
   615 	thread2.Resume();
   616 
   617 	//thread2 should be waiting for data available
   618 	test (thread2stat == KRequestPending);
   619 	aQueue.SendBlocking(&dummydata, sizeof (TInt));
   620 	User::WaitForRequest(thread2stat);
   621 	test (thread2stat == KErrNone);
   622 	test (thread2.ExitType() == EExitKill);
   623 	CLOSE_AND_WAIT(thread2);
   624 	//thread 2 has exited OK
   625 
   626 	//empty the queue
   627 	aQueue.ReceiveBlocking(ptr, aSize);
   628 	test (*(TInt*)ptr == dummydata);
   629 
   630 	//create thread 2 again 
   631 	ret = thread2.Create(KThread2Name, notifyDataAvailableEntryPoint, KDefaultStackSize, KHeapSize, KHeapSize, &data);
   632 	test(KErrNone == ret);
   633 	thread2.Logon(thread2stat);
   634 	thread2.Resume();
   635 
   636 	//create thread3
   637 	ret = thread3.Create(KThread3Name, notifyDataAvailableEntryPoint, KDefaultStackSize, KHeapSize, KHeapSize, &data);
   638 	test(KErrNone == ret);
   639 	thread3.Logon(thread3stat);
   640 	User::SetJustInTime(EFalse);
   641 	User::After(10000);
   642 	thread3.Resume();
   643 
   644 	User::WaitForRequest(thread3stat);
   645 	User::SetJustInTime(jit);
   646 	
   647 	test (thread3.ExitType() == EExitPanic);
   648 	test (thread3.ExitReason() == EMsgQueueRequestPending);
   649 	CLOSE_AND_WAIT(thread3);
   650 
   651 	aQueue.SendBlocking(&dummydata, sizeof (TInt));
   652 	User::WaitForRequest(thread2stat);
   653 	test (thread2stat == KErrNone);
   654 	test (thread2.ExitType() == EExitKill);
   655 	CLOSE_AND_WAIT(thread2);
   656 
   657 	//empty the queue
   658 	aQueue.ReceiveBlocking(ptr, aSize);
   659 	test (*(TInt*)ptr == dummydata);
   660 
   661 	User::Free(ptr);
   662 	}
   663 
   664 
   665 class TTemplateTestData
   666 	{
   667 public:
   668 	TTemplateTestData();
   669 	TTemplateTestData(TInt a, TUint b, TUint8 c, TBool d, TInt e);
   670 	TInt first;
   671 	TUint second;
   672 	TUint8 bob;
   673 	TBool fred;
   674 	TInt chipper;
   675 	};
   676 
   677 TTemplateTestData::TTemplateTestData()  : first(0), second(0), bob(0), fred(0), chipper(0)
   678 	{
   679 	}
   680 
   681 TTemplateTestData::TTemplateTestData(TInt a, TUint b, TUint8 c, TBool d, TInt e) : first(a), second(b), bob(c), fred(d), chipper(e)
   682 	{
   683 	}
   684 
   685 
   686 enum TQueueType {ECreateLocal, ECreateGlobal};
   687 
   688 LOCAL_C TInt illegalQueueCreation(TAny* aData)
   689 	{
   690 	TData& data = *(TData *)aData;
   691 	switch (data.iTest)
   692 		{
   693 		case ECreateLocal:	//CreateLocal
   694 			{
   695 			RMsgQueueBase queue;
   696 			queue.CreateLocal(data.iSlots, data.iSize);
   697 			break;
   698 			}
   699 		case ECreateGlobal:	//create global named
   700 			{
   701 			RMsgQueueBase queue;
   702 			queue.CreateGlobal(KGLobalName1,  data.iSlots, data.iSize);
   703 			break;
   704 			}
   705 		}
   706 	test(0);	//should never get here.  This'll make a Kern Exec 0! as tries to use console from different thread
   707 	return 0;
   708 	}
   709 
   710 
   711 LOCAL_C void TestIllegalCreation(TInt aSlots, TInt aSize, TQueueType aQueueType, TInt aExpectedReason)
   712 		{
   713 		RThread thread;
   714 		TData data(NULL, aSize, aSlots, aQueueType, NULL);
   715 		TRequestStatus threadstat;
   716 		TBool jit = User::JustInTime();
   717 		User::SetJustInTime(EFalse);
   718 		TInt ret = thread.Create(KThread2Name, illegalQueueCreation, KDefaultStackSize, KHeapSize, KHeapSize, &data);
   719 		test(KErrNone == ret);
   720 		thread.Logon(threadstat);
   721 		thread.Resume();
   722 		User::WaitForRequest(threadstat);
   723 		test (thread.ExitType() == EExitPanic);
   724 		test (thread.ExitReason() == aExpectedReason);
   725 		CLOSE_AND_WAIT(thread);
   726 		User::SetJustInTime(jit);
   727 		}
   728 
   729 TInt DyingDataAvailableThread( TAny* )
   730 	{
   731 	RMsgQueue<TInt>	theQ;
   732 	if( KErrNone != theQ.OpenGlobal(_L("TestNotifiedThreadDied")) )
   733 		User::Panic( _L("TESTTH"), 0 );
   734 
   735 	TRequestStatus stat;
   736 	theQ.NotifyDataAvailable( stat );
   737 	// now just exit
   738 	return KErrNone;
   739 	}
   740 
   741 TInt DyingSpaceAvailableThread( TAny* )
   742 	{
   743 	RMsgQueue<TInt>	theQ;
   744 	if( KErrNone != theQ.OpenGlobal(_L("TestNotifiedThreadDied")) )
   745 		User::Panic( _L("TESTTH"), 0 );
   746 
   747 	TRequestStatus stat;
   748 	theQ.NotifySpaceAvailable( stat );
   749 	// now just exit
   750 	return KErrNone;
   751 	}
   752 
   753 struct TThreadParams
   754 	{
   755 	TInt imyQHandle;
   756 	TRequestStatus* iRequest;
   757 	};
   758 	
   759 TInt DyingRequestDataNotification(TAny* aThreadParams)
   760 	{
   761 	CTrapCleanup* trapHandler = CTrapCleanup::New();
   762 	if(!trapHandler)
   763 		return KErrNoMemory;
   764 
   765 	TThreadParams* tp = reinterpret_cast<TThreadParams*>(aThreadParams);
   766 	
   767 	RMsgQueue<TInt> msgQue2;
   768 	msgQue2.SetHandle(tp->imyQHandle);
   769 	msgQue2.NotifyDataAvailable(*tp->iRequest);
   770 	
   771 	delete trapHandler;
   772 	return KErrNone;
   773 	}
   774 
   775 void TestNotifiedThreadDied()
   776 {
   777 	RThread th;
   778 	TRequestStatus stat;
   779 	RMsgQueue<TInt>	myQ;
   780 	test( KErrNone == myQ.CreateGlobal( _L("TestNotifiedThreadDied"), 1 ) );
   781 
   782 	//Test when thread waiting on data available dies
   783 	test( KErrNone == th.Create( _L("DyingDataAvailableThread"), DyingDataAvailableThread, 1024, 1024, 8192, NULL ) );
   784 	th.Logon( stat );
   785 	th.Resume();
   786 	User::WaitForRequest( stat );
   787 	test(stat.Int()==KErrNone);
   788 	
   789 	User::After( 1000000 );
   790 
   791 	myQ.NotifyDataAvailable( stat );
   792 	myQ.CancelDataAvailable();
   793 	CLOSE_AND_WAIT(th);
   794 
   795 	//Test when thread waiting on space available dies
   796 	myQ.Send(0);//This will fill in the whole message queue and block any thread waiting on space available.
   797 
   798 	test( KErrNone == th.Create( _L("DyingSpaceAvailableThread"), DyingSpaceAvailableThread, 1024, 1024, 8192, NULL ) );
   799 	th.Logon( stat );
   800 	th.Resume();
   801 	User::WaitForRequest( stat );
   802 	test(stat.Int()==KErrNone);
   803 	
   804 	User::After( 1000000 );
   805 
   806 	myQ.NotifySpaceAvailable( stat );
   807 	myQ.CancelSpaceAvailable();
   808 	myQ.Close();
   809 	CLOSE_AND_WAIT(th);
   810 
   811 	// Calling cancel notification should not crash as the thread that requested notification dies
   812 	test( KErrNone == myQ.CreateLocal(1, EOwnerProcess));
   813 
   814 	TThreadParams tp;
   815 	tp.imyQHandle = myQ.Handle();
   816 	tp.iRequest = &stat;
   817 
   818 	test( KErrNone == th.Create(_L("DyingRequestDataNotificationThread"), DyingRequestDataNotification, KDefaultStackSize, 
   819 									KHeapSize, KHeapSize, reinterpret_cast<TAny*>(&tp)));
   820 	TRequestStatus status;
   821 	th.Logon(status);
   822 	th.Resume();
   823 	th.Close();
   824 
   825 	User::WaitForRequest(status);
   826 	test(status.Int() == KErrNone);
   827 
   828 	myQ.CancelDataAvailable();
   829 	myQ.Close();
   830 
   831 }
   832 
   833 LOCAL_C void RunTests(void)
   834 	{
   835 	TInt ret = KErrNone;
   836 	test.Start(_L("Testing"));
   837 
   838 
   839 	RMsgQueueBase mqueue;
   840 
   841 //	LOCAL message queues
   842 
   843 
   844 	test.Next(_L("Check when thread dies waiting to be notified."));
   845 	TestNotifiedThreadDied();
   846 
   847 	test.Next(_L("Create private message queue with 0 length params"));
   848 	TestIllegalCreation(0,0,ECreateLocal, EMsgQueueInvalidLength);
   849 
   850 	test.Next(_L("Create private message queue with 0  slots"));
   851 	TestIllegalCreation(0,4,ECreateLocal, EMsgQueueInvalidSlots);
   852 
   853 	test.Next(_L("Create private message queue with 0 size message"));
   854 	TestIllegalCreation(5, 0, ECreateLocal, EMsgQueueInvalidLength);
   855 
   856 	test.Next(_L("Create private message queue with none multiple of 4 size message"));
   857 	TestIllegalCreation(5, 9, ECreateLocal, EMsgQueueInvalidLength);
   858 
   859 	test.Next(_L("Create private message queue with illegal max length "));
   860 	TestIllegalCreation(8,RMsgQueueBase::KMaxLength+1, ECreateLocal, EMsgQueueInvalidLength);
   861 
   862 
   863 	test.Next(_L("Create private message queue, 43 slots, length 8"));
   864 	ret = mqueue.CreateLocal(43,8, EOwnerThread);
   865 	test (KErrNone == ret);
   866 	mqueue.Close();
   867 
   868 	test.Next(_L("Create private message queue with max length "));
   869 	ret = mqueue.CreateLocal(8, RMsgQueueBase::KMaxLength, EOwnerProcess);
   870 	test (KErrNone == ret);
   871 	mqueue.Close();
   872 
   873 	test.Next(_L("test private message queue functionality"));
   874 	
   875 	test.Printf(_L("two slots, small queue"));
   876 	ret = mqueue.CreateLocal(2, 4);
   877 	test(KErrNone == ret);
   878 	SingleThreadedTests(mqueue, 2, 4);
   879 	MultiThreadedTests(mqueue, 2, 4);
   880 	mqueue.Close();
   881 
   882 	test.Printf(_L("16 slots, max queue"));
   883 	ret = mqueue.CreateLocal(16, RMsgQueueBase::KMaxLength);
   884 	test(KErrNone == ret);
   885 	SingleThreadedTests(mqueue, 16, RMsgQueueBase::KMaxLength);
   886 	MultiThreadedTests(mqueue, 16, RMsgQueueBase::KMaxLength);
   887 	mqueue.Close();
   888 
   889 	test.Printf(_L("big slots, max queue"));
   890 	ret = mqueue.CreateLocal(KMaxTInt, RMsgQueueBase::KMaxLength);
   891 	test(KErrNoMemory == ret);
   892 
   893 
   894 	/**************************************************************************/
   895 //	GLOBAL Named message queues
   896 	test.Next(_L("Create global named message queue with 0 length params"));
   897 	TestIllegalCreation(0, 0, ECreateGlobal, EMsgQueueInvalidLength);
   898 
   899 	test.Next(_L("Create global named message queue with 0  slots"));
   900 	TestIllegalCreation(0, 4, ECreateGlobal, EMsgQueueInvalidSlots);
   901 
   902 	test.Next(_L("Create global message queue with 0 size message"));
   903 	TestIllegalCreation(5, 0, ECreateGlobal, EMsgQueueInvalidLength);
   904 
   905 	test.Next(_L("Create global message queue with none multiple of 4 size message"));
   906 	TestIllegalCreation(5, 9, ECreateGlobal, EMsgQueueInvalidLength);
   907 
   908 	test.Next(_L("Create global named message queue with illegal max length "));
   909 	TestIllegalCreation(8, RMsgQueueBase::KMaxLength+1, ECreateGlobal, EMsgQueueInvalidLength);
   910 
   911 	test.Next(_L("Create global named message queue"));
   912 	ret = mqueue.CreateGlobal(KGLobalName1, 10,8, EOwnerThread);
   913 	test (KErrNone == ret);
   914 	mqueue.Close();
   915 
   916 	test.Next(_L("Create global named message queue with max length "));
   917 	ret = mqueue.CreateGlobal(KGLobalName1, 8, RMsgQueueBase::KMaxLength, EOwnerProcess);
   918 	test (KErrNone == ret);
   919 	mqueue.Close();
   920 
   921 	test.Next(_L("test global named message queue functionality"));
   922 	
   923 	test.Printf(_L("small queue, two slots"));
   924 	ret = mqueue.CreateGlobal(KGLobalName1, 2, 4);
   925 	test(KErrNone == ret);
   926 	SingleThreadedTests(mqueue, 2, 4);
   927 	MultiThreadedTests(mqueue, 2, 4);
   928 	mqueue.Close();
   929 
   930 	test.Printf(_L("max queue, 16 slots"));
   931 	ret = mqueue.CreateGlobal(KGLobalName1, 16, RMsgQueueBase::KMaxLength);
   932 	test(KErrNone == ret);
   933 	SingleThreadedTests(mqueue, 16, RMsgQueueBase::KMaxLength);
   934 	MultiThreadedTests(mqueue, 16, RMsgQueueBase::KMaxLength);
   935 	mqueue.Close();
   936 
   937 	test.Printf(_L("32byte queue, 1000 slots"));
   938 	ret = mqueue.CreateGlobal(KGLobalName1, 1000, 32);
   939 	test(KErrNone == ret);
   940 	SingleThreadedTests(mqueue, 1000, 32);
   941 	MultiThreadedTests(mqueue, 1000, 32);
   942 	mqueue.Close();
   943 
   944 	test.Printf(_L("12 byte queue, 1 slot"));
   945 	ret = mqueue.CreateGlobal(KGLobalName1, 1, 12);
   946 	test(KErrNone == ret);
   947 	SingleThreadedTests(mqueue, 1, 12);
   948 	MultiThreadedTests(mqueue, 1, 12);
   949 	mqueue.Close();
   950 
   951 
   952 	test.Printf(_L("max queue, maxint! slots"));
   953 	ret = mqueue.CreateGlobal(KGLobalName1, KMaxTInt, RMsgQueueBase::KMaxLength);
   954 	test(KErrNoMemory == ret);
   955 
   956 	_LIT(KNonQueueName,"non-queue name");
   957 	test.Printf(_L("open a non-existant queue"));
   958 	ret = mqueue.OpenGlobal(KNonQueueName, EOwnerProcess);
   959 	test(ret == KErrNotFound);
   960 
   961 
   962 	ret = mqueue.CreateGlobal(KGLobalName1, 16, 4);
   963 	test(KErrNone == ret);
   964 	SingleThreadedTests(mqueue, 16, 4);
   965 	MultiThreadedTests(mqueue, 16, 4);
   966 	RMsgQueueBase open;
   967 
   968 	ret = open.OpenGlobal(KGLobalName1);
   969 	test(KErrNone == ret);
   970 	SingleThreadedTests(open, 16,4);
   971 	MultiThreadedTests(open, 16, 4);
   972 
   973 
   974 	test.Next(_L("Send a legal message through"));
   975 	TInt src = 45;
   976 	TInt dst = 0;
   977 	ret = mqueue.Send(&src, sizeof (TInt));
   978 	test(ret == KErrNone);
   979 
   980 	test.Next(_L("Receive legal message"));
   981 	ret = open.Receive(&dst, 4);
   982 	test(ret == KErrNone);
   983 	test (src == dst);
   984 
   985 	test.Next(_L("Send a legal message through"));
   986 	ret = mqueue.Send(&src, sizeof (TInt));
   987 	test(ret == KErrNone);
   988 
   989 	open.Close();
   990 	mqueue.Close();
   991 	
   992 
   993 	ret = mqueue.CreateGlobal(KNullDesC, 5, 4);
   994 	test(KErrNone == ret);
   995 	SingleThreadedTests(mqueue, 5,4);
   996 	MultiThreadedTests(mqueue, 5, 4);
   997 
   998 	ret = open.OpenGlobal(KNullDesC);
   999 	test(KErrNotFound == ret);
  1000 
  1001 	mqueue.Close();
  1002 	
  1003 
  1004 	test.Next(_L("Multi Process Queue Tests"));
  1005 	
  1006 _LIT(KQueueA, "A");
  1007 _LIT(KQueueB, "B");
  1008 _LIT(KProcessName, "T_MQUEUEECHO.EXE");
  1009 
  1010 	RMsgQueueBase inQueue;
  1011 	RMsgQueueBase outQueue;
  1012 
  1013 	TInt sizes[6] = {4,8,16,32,100,256};
  1014 
  1015 	TInt x;
  1016 	for (x = 0; x < 6; x++)
  1017 		{
  1018 		TUint8* p = (TUint8*)User::Alloc(sizes[x]);
  1019 		TRequestStatus stat;
  1020 		test (p != NULL);
  1021 		ret = inQueue.CreateGlobal(KQueueB, 1, sizes[x]);
  1022 		test (KErrNone == ret);
  1023 		ret = outQueue.CreateGlobal(KQueueA, 1, sizes[x]);
  1024 		test (KErrNone == ret);
  1025 
  1026 		//start other process
  1027 		RProcess proc;
  1028 		ret = proc.Create(KProcessName, KNullDesC);
  1029 		test (KErrNone == ret);
  1030 
  1031 		//logon to it
  1032 		proc.Logon(stat);
  1033 
  1034 		proc.Resume();
  1035 
  1036 		TInt y[64] = {1000};
  1037 
  1038 		while (--y[0] >= 0)
  1039 			{
  1040 			outQueue.SendBlocking(&y,sizes[x]);
  1041 			inQueue.ReceiveBlocking(p, sizes[x]);
  1042 			test (y[0] == *(TInt*)p);
  1043 			}
  1044 		
  1045 		User::Free(p);
  1046 		inQueue.Close();
  1047 		outQueue.Close();
  1048 
  1049 		//wait for the process to terminate
  1050 		User::WaitForRequest(stat);
  1051 		test(stat == KErrNone);
  1052 		CLOSE_AND_WAIT(proc);
  1053 		}
  1054 
  1055 	test.Next(_L("test templated queue"));
  1056 	RMsgQueue<TTemplateTestData> templateQueue;
  1057 	TTemplateTestData ch(1,2,3,ETrue,4);
  1058 	TTemplateTestData ch2;
  1059 	TTemplateTestData ch3;
  1060 
  1061 	test(KErrNone == templateQueue.CreateLocal(12));
  1062 
  1063 	test (KErrNone == templateQueue.Send(ch));
  1064 	test (ch.first != ch2.first);
  1065 	test (ch.chipper != ch2.chipper);
  1066 	test (KErrNone == templateQueue.Receive(ch2));
  1067 	test (ch.first == ch2.first);
  1068 	test (ch.chipper == ch2.chipper);
  1069 
  1070 	templateQueue.SendBlocking(ch);
  1071 	test (ch.first != ch3.first);
  1072 	test (ch.chipper != ch3.chipper);
  1073 	templateQueue.ReceiveBlocking(ch3);
  1074 	test (ch.first == ch3.first);
  1075 	test (ch.chipper == ch3.chipper);
  1076 
  1077 	templateQueue.Close();
  1078 
  1079 	test(KErrNone == templateQueue.CreateGlobal(KNullDesC, 79));
  1080 	templateQueue.Close();
  1081 
  1082 _LIT(KTestName, "testQueue");
  1083 
  1084 	test(KErrNone == templateQueue.CreateGlobal(KTestName, 986));
  1085 
  1086 	RMsgQueue<TTemplateTestData> templateQueue2;
  1087 	test(KErrNone == templateQueue2.OpenGlobal(KTestName));
  1088 	templateQueue.Close();
  1089 	templateQueue2.Close();
  1090 
  1091 	
  1092 	test.Next(_L("Ending test.\n"));
  1093 	test.End();
  1094 	
  1095 	test.Close();
  1096 	}
  1097 
  1098 GLDEF_C TInt E32Main()
  1099 //
  1100 //
  1101     {
  1102 	test.Title();
  1103 
  1104 	// Turn off evil lazy dll unloading
  1105 	RLoader l;
  1106 	test(l.Connect()==KErrNone);
  1107 	test(l.CancelLazyDllUnload()==KErrNone);
  1108 	l.Close();
  1109 	
  1110 	RunTests();
  1111 	return KErrNone;
  1112     }
  1113