Update contrib.
1 // Copyright (c) 1998-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".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // e32test\misc\t_ipccpy.cpp
16 // Test and benchmark IPC reading, writing, copying.
18 // RBusLogicalChannel, DLogicalChannel.
20 // - Load the specified logical device driver, open a channel to it, allocate
21 // a cell of specified size from the current thread's heap, get Kernel HAL
22 // memory model information.
23 // - Make a synchronous Kernel Executive type request to the logical channel
24 // to write specified data to the buffer, read the data and calculate the
25 // time taken for writing and reading the data. Benchmark the time required
26 // to for 1000 64K user->kernel and kernel->user copies.
27 // - Create a chunk, get a pointer to the base of the chunk's reserved region,
28 // create a server thread, establish a session with the server, signal
29 // completion of the client's request when message is received, read,
30 // write specified bits and check it is as expected.
31 // Platforms/Drives/Compatibility:
33 // Assumptions/Requirement/Pre-requisites:
34 // Failures and causes:
35 // Base Port information:
43 #include "../mmu/mmudetect.h"
46 RTest test(_L("T_IPCCPY"));
55 TUint8* Unaligned=Bss+1;
57 TLinAddr HwChunkAddr[RIpcCpy::ENumHwChunkTypes];
58 TPtr8 UserDes(Buffer+96,96,96);
63 TUint32 mm_attr=MemModelAttributes();
64 TUint32 mm_type=mm_attr & EMemModelTypeMask;
67 case EMemModelTypeDirect:
68 RamDrive=(TUint8*)0; // not used anyway
69 Nonexistent=(TUint8*)0xa8000000;
71 case EMemModelTypeMoving:
72 RamDrive=(TUint8*)0x40000000;
73 Nonexistent=(TUint8*)0x60f00000;
75 case EMemModelTypeMultiple:
76 RamDrive=(TUint8*)0xa0000000;
77 Nonexistent=(TUint8*)0xfe000000;
79 case EMemModelTypeFlexible:
81 Nonexistent=(TUint8*)0x8ff00000;
83 case EMemModelTypeEmul:
84 RamDrive=(TUint8*)0; // not used anyway
85 Nonexistent=(TUint8*)0xf0000000;
91 new (&UserDes) TPtr8(Buffer+96,96,96);
92 Ipccpy.HardwareChunks(HwChunkAddr,UserDes);
93 test.Printf(_L("Buffer=%08x\n"),Buffer);
94 test.Printf(_L("Bss=%08x\n"),Bss);
95 test.Printf(_L("Kern=%08x\n"),Kern);
96 test.Printf(_L("RamDrive=%08x\n"),RamDrive);
97 test.Printf(_L("Nonexistent=%08x\n"),Nonexistent);
98 test.Printf(_L("Unaligned=%08x\n"),Unaligned);
99 test.Printf(_L("HwChunkSupRw=%08x\n"),HwChunkAddr[RIpcCpy::EHwChunkSupRw]);
100 test.Printf(_L("HwChunkUserRw=%08x\n"),HwChunkAddr[RIpcCpy::EHwChunkUserRw]);
101 test.Printf(_L("HwChunkUserRo=%08x\n"),HwChunkAddr[RIpcCpy::EHwChunkUserRo]);
104 _LIT(KLitKernExec,"KERN-EXEC");
106 void TestEq(TInt a, TInt b, TInt l);
107 void Test(TBool c, TInt l);
109 #define TESTEQ(a,b) TestEq((a),(b),__LINE__)
110 #define TEST(c) Test((c),__LINE__)
112 void TestEq(TInt a, TInt b, TInt l)
116 if (TUint32(RThread().Id())==MainId)
118 test.Printf(_L("Line %d a=%d, b=%d\n"),l,a,b);
122 User::Panic(_L("TESTEQ"),l);
126 void Test(TBool c, TInt l)
130 if (TUint32(RThread().Id())==MainId)
132 test.Printf(_L("Line %d FAIL\n"),l);
136 User::Panic(_L("TEST"),l);
145 TInt iMode; // bit 0 = 1 for 16 bit, bit 1 = 1 for write
148 class RLocalSession : public RSessionBase
151 TInt Connect(RServer2 aSrv,TRequestStatus* aStat)
152 {return CreateSession(aSrv,TVersion(),-1,EIpcSession_Unsharable,0,aStat);}
153 void Test(const TAny* aRemote)
154 {Send(0,TIpcArgs((const TDesC8*)aRemote,(const TDesC16*)aRemote,(TDes8*)aRemote,(TDes16*)aRemote));}
161 TInt IpcTestFn(TAny* aInfo)
163 SIpcTestInfo& i=*(SIpcTestInfo*)aInfo;
165 if (IpcServer.Handle())
168 TESTEQ(IpcServer.CreateGlobal(KNullDesC),KErrNone);
171 TESTEQ(sess.Connect(IpcServer,&stat),KErrNone);
173 IpcServer.Receive(m);
174 m.Complete(KErrNone); // connect
175 User::WaitForRequest(stat); // connection message report
176 sess.Test(i.iRemote);
177 IpcServer.Receive(m);
184 TDesC8* pR=(TDesC8*)i.iRemote;
185 TDes8* pL=(TDes8*)i.iLocal;
186 r=m.Read(0,*pL,i.iOffset);
189 TESTEQ(pL->Length(),pR->Length()-i.iOffset);
190 TEST(*pL==pR->Mid(i.iOffset));
196 TDesC16* pR=(TDesC16*)i.iRemote;
197 TDes16* pL=(TDes16*)i.iLocal;
198 r=m.Read(1,*pL,i.iOffset);
201 TESTEQ(pL->Length(),pR->Length()-i.iOffset);
202 TEST(*pL==pR->Mid(i.iOffset));
208 TDes8* pR=(TDes8*)i.iRemote;
209 TDesC8* pL=(TDesC8*)i.iLocal;
210 r=m.Write(2,*pL,i.iOffset);
213 TESTEQ(pR->Length(),pL->Length()+i.iOffset);
214 TEST(*pL==pR->Mid(i.iOffset));
220 TDes16* pR=(TDes16*)i.iRemote;
221 TDesC16* pL=(TDesC16*)i.iLocal;
222 r=m.Write(3,*pL,i.iOffset);
225 TESTEQ(pR->Length(),pL->Length()+i.iOffset);
226 TEST(*pL==pR->Mid(i.iOffset));
231 User::Panic(_L("MODE"),i.iMode);
240 void _DoIpcTest(const TAny* aLocal, const TAny* aRemote, TInt aOffset, TInt aMode, const TDesC* aPanicCat, TInt aResult, TInt aLine)
242 test.Printf(_L("Line %d\n"),aLine);
245 info.iRemote=aRemote;
246 info.iOffset=aOffset;
250 // do test in this thread
251 TInt r=IpcTestFn(&info);
255 TBool jit=User::JustInTime();
257 TInt r=t.Create(KNullDesC(),IpcTestFn,0x2000,NULL,&info);
261 User::SetJustInTime(EFalse);
263 User::WaitForRequest(s);
264 User::SetJustInTime(jit);
265 test(t.ExitType()==EExitPanic);
266 test(t.ExitCategory()==*aPanicCat);
267 TESTEQ(t.ExitReason(),aResult);
271 void DoIpcTest(const TUint8* aLocal, const TUint8* aRemote, TInt aLength, TInt aMode, const TDesC* aPanicCat, TInt aResult, TInt aLine)
273 TPtr8 local((TUint8*)aLocal,aLength,aLength);
274 TPtr8 remote((TUint8*)aRemote,aLength,aLength);
275 _DoIpcTest(&local,&remote,0,aMode,aPanicCat,aResult,aLine);
278 void DoIpcTest(const TUint8* aLocal, const TDesC8& aRemote, TInt aLength, TInt aMode, const TDesC* aPanicCat, TInt aResult, TInt aLine)
280 TPtr8 local((TUint8*)aLocal,aLength,aLength);
281 _DoIpcTest(&local,&aRemote,0,aMode,aPanicCat,aResult,aLine);
284 void TestIpcCopyErrors()
287 TInt r=c.CreateDisconnectedLocal(0,0,0x500000);
289 r=c.Commit(0,0x1000);
291 r=c.Commit(0x2000,0x1000);
293 r=c.Commit(0x3ff000,0x1000);
296 test.Printf(_L("Disc=%08x\n"),Disc);
297 DoIpcTest(Buffer,(const TUint8*)&TestEq,100,0,NULL,KErrNone,__LINE__);
298 DoIpcTest(Buffer,(const TUint8*)&TestEq,100,2,NULL,KErrBadDescriptor,__LINE__);
299 DoIpcTest((const TUint8*)&TestEq,Buffer,100,2,NULL,KErrNone,__LINE__);
300 DoIpcTest((const TUint8*)&TestEq,Buffer,100,0,&KLitKernExec,ECausedException,__LINE__);
301 DoIpcTest(Buffer,Nonexistent,100,0,NULL,KErrBadDescriptor,__LINE__);
302 DoIpcTest(Buffer,Nonexistent,100,2,NULL,KErrBadDescriptor,__LINE__);
303 DoIpcTest(Nonexistent,Buffer,100,2,&KLitKernExec,ECausedException,__LINE__);
304 DoIpcTest(Nonexistent,Buffer,100,0,&KLitKernExec,ECausedException,__LINE__);
305 DoIpcTest(Buffer,Unaligned,100,0,NULL,KErrNone,__LINE__);
306 DoIpcTest(Buffer,Unaligned,100,2,NULL,KErrNone,__LINE__);
307 DoIpcTest(Unaligned,Buffer,100,2,NULL,KErrNone,__LINE__);
308 DoIpcTest(Unaligned,Buffer,100,0,NULL,KErrNone,__LINE__);
310 DoIpcTest(Disc+4001,Buffer,95,0,NULL,KErrNone,__LINE__);
312 DoIpcTest(Disc+4001,Buffer,96,0,&KLitKernExec,ECausedException,__LINE__);
313 DoIpcTest(Buffer,Disc+4001,95,0,NULL,KErrNone,__LINE__);
315 DoIpcTest(Buffer,Disc+4001,96,0,NULL,KErrBadDescriptor,__LINE__);
320 // test descriptor stored stradling chunk end...
321 pdes = (TPtr8*)(Disc+0x3ffff4);
322 memcpy(pdes,&UserDes,12);
323 DoIpcTest(Buffer,*pdes,pdes->Size(),0,NULL,KErrNone,__LINE__);
324 pdes = (TPtr8*)(Disc+0x3ffff8);
325 memcpy(pdes,&UserDes,8);
326 DoIpcTest(Buffer,*pdes,pdes->Size(),0,NULL,KErrBadDescriptor,__LINE__);
327 pdes = (TPtr8*)(Disc+0x3ffffc);
328 memcpy(pdes,&UserDes,4);
329 DoIpcTest(Buffer,*pdes,pdes->Size(),0,NULL,KErrBadDescriptor,__LINE__);
330 r=c.Commit(0x400000,0x1000);
332 pdes = (TPtr8*)(Disc+0x3ffff4);
333 memcpy(pdes,&UserDes,12);
334 DoIpcTest(Buffer,*pdes,pdes->Size(),0,NULL,KErrNone,__LINE__);
335 pdes = (TPtr8*)(Disc+0x3ffff8);
336 memcpy(pdes,&UserDes,12);
337 DoIpcTest(Buffer,*pdes,pdes->Size(),0,NULL,KErrNone,__LINE__);
338 pdes = (TPtr8*)(Disc+0x3ffffc);
339 memcpy(pdes,&UserDes,12);
340 DoIpcTest(Buffer,*pdes,pdes->Size(),0,NULL,KErrNone,__LINE__);
347 DoIpcTest(Disc+0x100000,Buffer,96,0,&KLitKernExec,ECausedException,__LINE__);
348 DoIpcTest(Buffer,Disc+0x100000,96,0,NULL,KErrBadDescriptor,__LINE__);
349 DoIpcTest(RamDrive,Buffer,4,0,&KLitKernExec,ECausedException,__LINE__);
350 DoIpcTest(Buffer,RamDrive,4,0,NULL,KErrBadDescriptor,__LINE__);
351 DoIpcTest(RamDrive,Buffer,4,2,&KLitKernExec,ECausedException,__LINE__);
352 DoIpcTest(Buffer,RamDrive,4,2,NULL,KErrBadDescriptor,__LINE__);
355 // if memory alising happens during IPC then the memory at 'Disc' would be aliased
356 // at KIPCAliasAddress and so would not be protected by MMU permission checks.
357 // However, the kernel should still prevent this, to avoid degrading process
358 // protection for memory in other parts of the alias region.
360 const TUint8* KIPCAliasAddress;
361 if((MemModelAttributes()&EMemModelTypeMask) == EMemModelTypeFlexible)
362 KIPCAliasAddress = (TUint8*)0x7e000000;
364 KIPCAliasAddress = (TUint8*)0xc0400000;
366 const TUint8* KIPCAliasAddress = (TUint8*)0x00200000;
368 DoIpcTest(KIPCAliasAddress,Disc,4,0,&KLitKernExec,ECausedException,__LINE__);
369 DoIpcTest(Disc,KIPCAliasAddress,4,0,NULL,KErrBadDescriptor,__LINE__);
370 DoIpcTest(KIPCAliasAddress,Disc,4,2,&KLitKernExec,ECausedException,__LINE__);
371 DoIpcTest(Disc,KIPCAliasAddress,4,2,NULL,KErrBadDescriptor,__LINE__);
374 if (HaveIPCKernProt())
376 DoIpcTest(Kern,Buffer,96,0,&KLitKernExec,ECausedException,__LINE__);
377 DoIpcTest(Buffer,Kern,96,0,NULL,KErrBadDescriptor,__LINE__);
378 TUint8* addrRW = (TUint8*)HwChunkAddr[RIpcCpy::EHwChunkSupRw];
381 DoIpcTest(Buffer,*(TDes8*)addrRW,96,0,NULL,KErrBadDescriptor,__LINE__);
382 DoIpcTest(Buffer,*(TDes8*)addrRW,96,2,NULL,KErrBadDescriptor,__LINE__);
383 DoIpcTest(addrRW+96,Buffer,96,0,&KLitKernExec,ECausedException,__LINE__);
384 DoIpcTest(Buffer,addrRW,96,0,NULL,KErrBadDescriptor,__LINE__);
385 DoIpcTest(addrRW+96,Buffer,96,2,&KLitKernExec,ECausedException,__LINE__);
386 DoIpcTest(Buffer,addrRW,96,2,NULL,KErrBadDescriptor,__LINE__);
390 if((MemModelAttributes()&EMemModelTypeMask) == EMemModelTypeMultiple
391 || (MemModelAttributes()&EMemModelTypeMask) == EMemModelTypeFlexible
394 // On multiple memory model, test IPC to Hardware Chunks.
395 // IPC to hardware chunks not supported on Moving Memory
396 TUint8* addrRW = (TUint8*)HwChunkAddr[RIpcCpy::EHwChunkUserRw];
399 DoIpcTest(Buffer,*(TDes8*)addrRW,96,0,NULL,KErrNone,__LINE__);
400 DoIpcTest(Buffer,*(TDes8*)addrRW,96,2,NULL,KErrNone,__LINE__);
401 DoIpcTest(addrRW+96,Buffer,96,0,NULL,KErrNone,__LINE__);
402 DoIpcTest(Buffer,addrRW,96,0,NULL,KErrNone,__LINE__);
403 DoIpcTest(addrRW+96,Buffer,96,2,NULL,KErrNone,__LINE__);
404 DoIpcTest(Buffer,addrRW,96,2,NULL,KErrNone,__LINE__);
405 DoIpcTest(addrRW+96,addrRW,96,0,NULL,KErrNone,__LINE__);
406 DoIpcTest(addrRW+96,addrRW,96,2,NULL,KErrNone,__LINE__);
408 TUint8* addrRO = (TUint8*)HwChunkAddr[RIpcCpy::EHwChunkUserRo];
409 if(addrRO && HaveWriteProt())
411 DoIpcTest(Buffer,*(TDes8*)addrRO,96,0,NULL,KErrNone,__LINE__);
412 DoIpcTest(Buffer,*(TDes8*)addrRO,96,2,&KLitKernExec,EBadIpcDescriptor,__LINE__);
413 DoIpcTest(addrRO+96,Buffer,96,0,&KLitKernExec,ECausedException,__LINE__);
414 DoIpcTest(Buffer,addrRO,96,0,NULL,KErrNone,__LINE__);
415 DoIpcTest(addrRO+96,Buffer,96,2,NULL,KErrNone,__LINE__);
416 DoIpcTest(Buffer,addrRO,96,2,NULL,KErrBadDescriptor,__LINE__);
417 DoIpcTest(addrRW+96,addrRO,96,0,NULL,KErrNone,__LINE__);
418 DoIpcTest(addrRW+96,addrRW,96,2,NULL,KErrNone,__LINE__);
419 DoIpcTest(addrRO+96,addrRO,96,0,&KLitKernExec,ECausedException,__LINE__);
420 DoIpcTest(addrRO+96,addrRW,96,2,NULL,KErrNone,__LINE__);
427 RMessage2 Msg1, Msg2;
429 TInt SendAndExit(TAny* aPtr)
432 TInt r=sess.Connect(IpcServer,NULL);
438 User::AfterHighRes(1000*CloseTime);
439 Msg1.Complete(0); // complete my own message! - this removes message reference to thread
443 void TestIpcAsyncClose()
446 // Create a 16MB chunk
447 const TInt desSize = 8*1024*1024;
449 test(chunk.CreateLocal(2 * desSize, 2 * desSize) == KErrNone);
450 test(chunk.Adjust(2 * desSize) == KErrNone);
452 TUint8* bigBuf=chunk.Base();
454 TUint8* bigBuf2=chunk.Base() + desSize;
456 TPtr8 bigBufPtr(bigBuf, desSize, desSize);
457 TPtr8 bigBufPtr2(bigBuf2, 0, desSize);
459 if (IpcServer.Handle())
461 TESTEQ(IpcServer.CreateGlobal(KNullDesC),KErrNone);
464 TInt r=t.Create(KNullDesC,SendAndExit,0x1000,NULL,&bigBufPtr);
466 TFullName fn(t.FullName());
469 t.SetPriority(EPriorityMuchMore);
472 IpcServer.Receive(Msg1); // connect
473 Msg1.Complete(KErrNone);
474 IpcServer.Receive(Msg1); // test message
475 IpcServer.Receive(Msg2); // wait/synch message
476 TUint32 initial = User::NTickCount();
477 r=Msg1.Read(2,bigBufPtr2,0); // arg2 is writable 8 bit descriptor
478 TUint32 final = User::NTickCount();
479 TUint32 elapsed = final - initial;
481 test.Printf(_L("*** WARNING! The big IPC only took %dms, which means the next test might fail! \n"),elapsed);
483 test.Printf(_L("Big IPC took %dms\n"),elapsed);
484 CloseTime = (TInt)(elapsed>>2);
486 IpcServer.Receive(Msg2); // disconnect
487 TUint32 disconnect = User::NTickCount();
489 // We expect this IPC read to fail part way through
490 r=Msg1.Read(2,bigBufPtr2,0); // arg2 is writable 8 bit descriptor
491 test.Printf(_L("counters: initial=%d final=%d disconnect=%d current=%d\n"),initial,final,disconnect,User::NTickCount());
492 test.Printf(_L("2nd Big IPC returned %d\n"),r);
495 Msg2.Complete(0); // complete session closure as well
496 User::WaitForRequest(s);
499 test(t.Open(fn)==KErrNotFound);
503 // User::Free(bigBuf);
504 // User::Free(bigBuf2);
510 TAny* bigbuf = User::Alloc(65536);
511 test(bigbuf != NULL);
513 TUint32 initial, final;
514 initial = User::NTickCount();
515 for (i=0; i<1000; ++i)
516 Ipccpy.BigWrite(bigbuf, 0);
517 final = User::NTickCount();
518 TUint32 wcal = final - initial;
519 initial = User::NTickCount();
520 for (i=0; i<1000; ++i)
521 Ipccpy.BigWrite(bigbuf, 65536);
522 final = User::NTickCount();
523 TUint32 write = final - initial;
524 test.Printf(_L("64K user->kernel copy takes %d us\n"), write - wcal);
525 initial = User::NTickCount();
526 for (i=0; i<1000; ++i)
527 Ipccpy.BigRead(bigbuf, 0);
528 final = User::NTickCount();
529 TUint32 rcal = final - initial;
530 initial = User::NTickCount();
531 for (i=0; i<1000; ++i)
532 Ipccpy.BigRead(bigbuf, 65536);
533 final = User::NTickCount();
534 TUint32 read = final - initial;
535 test.Printf(_L("64K kernel->user copy takes %d us\n"), read - rcal);
537 // User::After(10*1000*1000);
542 const TInt KTestChunkSize = 1024*1024;
543 const TInt KReadSize = 4096;
545 TInt IpcMultipleAliasesThread(TAny* aBuffer)
547 TBuf8<KReadSize> data;
548 TAny** dataStart = (TAny**)data.Ptr();
549 TAny** dataEnd = (TAny**)(data.Ptr()+KReadSize-sizeof(TAny*));
553 for(offset=0; offset<KTestChunkSize; offset+=KReadSize)
555 TInt r = IpcMesage.Read(0,data,offset);
558 if(data.Size()!=KReadSize)
560 TAny* expected = (TAny*)((TInt)aBuffer+offset);
561 if(*dataStart != expected)
563 RDebug::Printf("Offset=%x, expected %x but read %x",offset,expected,*dataStart);
566 expected = (TAny*)((TInt)aBuffer+offset+KReadSize-sizeof(TAny*));
567 if(*dataEnd != expected)
569 RDebug::Printf("Offset=%x, expected %x but read %x",offset,expected,*dataEnd);
577 This tests exercises the situation where multiple threads are doing IPC simultaneousely.
578 On the Multiple Memory Model, this aims to test the per-thread memory aliasing code.
579 (DMemModelThread::Alias and company)
581 void TestIpcMultipleThreads()
583 test.Start(_L("Test Multiple Threads IPC"));
585 // create chunk for threads to do IPC from...
587 TESTEQ(chunk.CreateLocal(KTestChunkSize,KTestChunkSize),KErrNone);
588 TAny** buffer = (TAny**)chunk.Base();
589 TAny** bufferEnd = (TAny**)((TInt)buffer+KTestChunkSize);
590 for(; buffer<bufferEnd; ++buffer)
593 // create a server message which test threads can use to do IPC memory operations
594 if (IpcServer.Handle())
596 TESTEQ(IpcServer.CreateGlobal(KNullDesC),KErrNone);
599 TESTEQ(sess.Connect(IpcServer,&stat),KErrNone);
601 IpcServer.Receive(m);
602 m.Complete(KErrNone); // connect
603 User::WaitForRequest(stat); // connection message report
604 TAny* ptrMem = User::Alloc(0x2000);
605 TPtr8* pptr = (TPtr8*)(((TInt)ptrMem&~0xfff)+0x1000-sizeof(TInt));
606 new (pptr) TPtr8(chunk.Base(),KTestChunkSize,KTestChunkSize); // create a TPtr8 which straddles a page boundary
608 IpcServer.Receive(IpcMesage);
610 // create some test threads...
611 const TInt KNumIpcThreads = 10;
612 RThread threads[KNumIpcThreads];
613 TRequestStatus stats[KNumIpcThreads];
615 for(i=0; i<KNumIpcThreads; i++)
617 TESTEQ(threads[i].Create(KNullDesC,IpcMultipleAliasesThread,KReadSize+0x1000,&User::Allocator(),chunk.Base()),KErrNone);
618 threads[i].Logon(stats[i]);
620 test.Printf(_L("Resuming threads...\n"));
621 for(i=0; i<KNumIpcThreads; i++)
624 User::After(10*1000000);
625 for(i=0; i<KNumIpcThreads; i++)
627 test(stats[i]==KRequestPending); // theads should still be running
630 // close chunk whilst test threads are still doing IPC...
631 test.Printf(_L("Closing chunk...\n"));
633 for(i=0; i<KNumIpcThreads; i++)
635 User::WaitForRequest(stats[i]);
636 TInt r=stats[i].Int();
637 test.Printf(_L("Thread %d result = %d\n"),i,r);
638 test(r==KErrBadDescriptor);
646 GLDEF_C TInt E32Main()
648 MainId=TUint32(RThread().Id());
649 // RThread().SetPriority(EPriorityAbsoluteForeground);
651 test.Start(_L("Load LDD"));
652 TInt r=User::LoadLogicalDevice(_L("D_IPCCPY"));
653 test(r==KErrNone || r==KErrAlreadyExists);
654 test.Next(_L("Open channel"));
657 test.Next(_L("Allocate heap buffer"));
658 Buffer=(TUint8*)User::Alloc(4096);
666 TestIpcMultipleThreads();
671 Mem::Fill(Buffer,272,0xcd);
672 TPtr8 ptr(Buffer,0,272);
673 Ipccpy.IpcCpy(s,ptr);
674 User::WaitForRequest(s);
678 test.Printf(_L("Error %d\n"),x);
682 TInt dest_offset=(x>>2)&3;
683 TInt length=(x>>4)+1;
686 for (i=0; i<dest_offset && err<0; ++i)
691 TUint8 v=(TUint8)src_offset;
692 for (i=0; i<length && err<0; ++i)
695 if (Buffer[i+dest_offset]!=v)
698 for (i=dest_offset+length; i<272 && err<0; ++i)
705 test.Printf(_L("Sequence number %03x\nSrcOffset %d, DestOffset %d, Length %d\n"),x,src_offset,dest_offset,length);
706 test.Printf(_L("First error at %d"),err);
707 for (i=0; i<272; i+=16)
710 test.Printf(_L("%03x:"),i);
713 test.Printf(_L(" %02x"),Buffer[i+j]);