Update contrib.
2 * Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
4 * This component and the accompanying materials are made available
5 * under the terms of the License "Eclipse Public License v1.0"
6 * which accompanies this distribution, and is available
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
9 * Initial Contributors:
10 * Nokia Corporation - initial contribution.
15 * Exercises the test implementation of the session count server,
16 * to test the base SCS functionality.
27 #include <e32ldr_private.h>
29 #include "rtestwrapper.h"
30 #include <e32def_private.h>
32 #include <scs/scscommon.h>
33 #include "scstestcommon.h"
34 #include "scstestclient.h"
36 const TInt KOneSecondUs = 1000 * 1000; ///< One second in microseconds.
38 /** Top-level test object renders stages and confirms conditions. */
39 static RTestWrapper test(_L("SCSTEST"));
42 This session handle is defined at the file level so each individual test
43 does not have to connect to the server.
45 static RScsTestSession sTestSession;
47 This subsession handle is defined at the file level so each individual test
48 does not have to connect to the server and create a subssesion.
50 static RScsTestSubsession sTestSubsession;
52 /** Arbitrary integer value used to construct subsession. */
53 static const TInt KSubsessValue = 10;
55 static void LetServerRun()
57 Sleep for 100ms so the server thread can run to clean up,
58 terminate, or just process the last request which it was sent.
61 User::After(100 * 1000);
64 // -------- OOM testing --------
66 static void RunOomTest(TInt (*aAllocFunc)(), void (*aFreeFunc)())
68 Run the supplied allocator function while forcing OOM on the server side.
69 On failure, this functions tests that the server heap is balanced. On
70 success, it runs the free function and also tests that the server heap is
73 @param aAllocFunc Function which allocates resources on the server heap.
74 @param aFreeFunc Frees the resources allocated with aAllocFunc. It should
75 only be necessary to call this function if aAllocFunc
76 succeeds. This argument can be NULL if there is no
77 corresponding free function.
80 TInt r = KErrNoMemory;
82 for (TInt i = 1; r == KErrNoMemory; ++i)
84 sTestSession.SetServerHeapFail(i);
88 test(r == KErrNone || r == KErrNoMemory);
89 if (r == KErrNone && aFreeFunc != NULL)
92 sTestSession.ResetServerHeapFail();
96 // -------- panic testing --------
99 To test that a client is panicked, pass a function with this
100 signature to TestPanic. It will be called from a new thread.
104 typedef void (*TPanicFunc)(RScsTestSession&);
106 static void ConfirmPanicReason(RThread aThread, TInt aExpectedReason)
108 Test the supplied thread was panicked with category
109 ScsImpl::KScsClientPanicCat and the supplied reason.
111 @param aThread Panicked thread.
112 @param aExpectedReason The thread should have been panicked with
114 @see ScsImpl::KScsClientPanicCat
117 TExitType exitType = aThread.ExitType();
118 TExitCategoryName exitCat = aThread.ExitCategory();
119 TInt exitReason = aThread.ExitReason();
121 test(exitType == EExitPanic);
122 test(exitCat == ScsImpl::KScsClientPanicCat);
123 test(exitReason == aExpectedReason);
126 static TInt TestPanicEntrypoint(TAny* aPtr)
128 This entrypoint is called by the panic thread. The
129 function connects to the SCS test server and passes
130 the handle to the function that should be panicked.
132 @param aPtr Standard entrypoint argument. This is actually
133 a pointer to the function to call with the connected
135 @return KErrNone. Required to satisfy entrypoint signature.
139 TInt r = s.Connect();
142 TPanicFunc f = TAnyPtrToFuncPtr<TPanicFunc>(aPtr);
145 test(EFalse); // should not reach here
149 static void TestPanic(TPanicFunc aFunc, TInt aExpectedReason)
151 Create a thread which should be panicked because it will
152 pass invalid data to the SCS test server. Test the thread
153 is panicked with the expected category and reason.
155 @param aFunc Function to call from panic thread.
156 @param aExpectedReason Reason with which the thread should
162 _L("ScsTestPanic"), TestPanicEntrypoint,
163 KDefaultStackSize, KMinHeapSize, KMinHeapSize, (TAny*) aFunc);
168 test(rs == KRequestPending);
169 TBool jit = User::JustInTime();
170 User::SetJustInTime(EFalse);
173 User::WaitForRequest(rs);
174 User::SetJustInTime(jit);
175 ConfirmPanicReason(thd, aExpectedReason);
179 // -------- open / close --------
181 /** Handle to a session which the test code attempts to open in server-side OOM. */
182 RScsTestSession sOomTestSession;
184 static TInt OpenOomSession()
186 This function is invoked by RunOomTest. It just
187 attempts to connect to the SCS test server.
189 @return Return code from RScsTestSession::Connect.
193 return sOomTestSession.Connect();
196 static void CloseOomSession()
198 Closes the session which was opened by OpenOomSession.
201 @pre OpenOomSession was successfully opened by OpenOomSession.
204 sOomTestSession.Close();
207 static void TestServerDeath()
209 test.Start(_L("TestServerDeath"));
211 test.Next(_L("Starting server without shutdown timer"));
212 // Create marker file to get server to run without a activity timeout
214 TInt r = fs.Connect();
216 (void) fs.Delete(KDisableScsTestServerTimeout());
219 r = file.Create(fs, KDisableScsTestServerTimeout(), EFileShareAny|EFileWrite);
224 RScsTestSession scsts;
228 test.Next(_L("Checking ShutdownServer is not allowed"));
229 r = scsts.ShutdownServer();
230 test(r == KErrNotSupported);
233 test.Next(_L("Doing an async call to check server does not attempt to restart the timer and crash"));
234 TPckgBuf<TInt> x1 = 1;
236 scsts.Treble(x1, rs1);
237 User::WaitForRequest(rs1);
239 test.Printf(_L("NukeServer - scstestserver.exe SHOULD panic\n"));
240 r = scsts.NukeServer();
241 test(r == KErrServerTerminated);
244 (void) fs.Delete(KDisableScsTestServerTimeout());
250 static void TestOpenClose()
252 Attempt to connect to the server when supplying default,
253 lower, and higher version numbers. Attempt to open a session
257 test.Start(_L("TestOpenClose"));
260 RScsTestSession scsts;
267 // lower-than-supported version
268 TVersion v = ScsTestImpl::Version();
270 r = scsts.Connect(v);
274 // supported version (should be same as default)
276 r = scsts.Connect(v);
280 // greater-than-supported version
282 r = scsts.Connect(v);
283 test(r == KErrNotSupported);
285 // test opening session when server running out of memory
286 r = sTestSession.Connect(); // required to send OOM commands
289 RunOomTest(OpenOomSession, CloseOomSession);
291 sTestSession.Close();
294 // Test closing server with an out standing request
298 TPckgBuf<TInt> x1 = 1;
300 scsts.Treble(x1, rs1);
301 // Bypass the presession close
302 RSessionBase *session = &scsts;
304 User::WaitForRequest(rs1);
305 test(rs1 == KErrCancel);
311 // -------- invalid session function --------
313 static void TestInvalidSessionFunction()
315 Send an unrecognized SCS code and confirm that it is
316 rejected with KErrNotSupported. This tests the SCS
319 Send an unrecognized function identifier to the session
320 and confirm that it is also rejected with KErrNotSupported.
321 This tests the test server session implementation.
324 test.Start(_L("TestInvalidSessionFunction"));
328 r = sTestSession.SendCustomFunction(ScsImpl::EScsUnused);
329 test(r == KErrNotSupported);
331 r = sTestSession.SendCustomFunction(ScsImpl::ECallSessionFunc | ScsTestImpl::ESessUnused);
332 test(r == KErrNotSupported);
337 // -------- synchronous session function --------
339 static void TestSyncSessionFunction()
341 Send a recognized function to the SCS test session,
342 and confirm that it is executed correctly.
345 test.Start(_L("TestSyncSessionFunction"));
348 TInt r = sTestSession.Double(x);
355 // -------- asynchronous session function --------
357 static TInt LaunchSessionTrebleOom()
359 Attempt to launch an asynchronous command on a session
360 under OOM conditions.
363 TPckgBuf<TInt> x = 3;
365 sTestSession.Treble(x, rs);
366 User::WaitForRequest(rs);
376 static void TestAsyncInvalidDescPanic(RScsTestSession& aSession)
378 Pass an invalid descriptor to the SCS test server.
379 The current thread should be panicked.
381 @param aSession Open session to SCS test server,
382 supplied by TestPanic.
388 aSession.Treble(*nullDes8, rs);
389 User::WaitForRequest(rs);
392 static void TestRequeueOutstandingPanic(RScsTestSession& aSession)
394 Attempt to requeue an asynchronous request which is still
395 outstanding. The current thread should be panicked.
397 @param aSession Connected session to SCS test server.
401 TPckgBuf<TInt> x1 = 1;
403 aSession.Treble(x1, rs1);
405 TPckgBuf<TInt> x2 = 2;
407 aSession.Treble(x2, rs2);
409 User::WaitForRequest(rs1, rs2);
410 User::WaitForRequest(rs1, rs2);
413 static void TestAsyncSessionFunction()
415 Test asynchronous session-relative functions.
417 Launch a request and wait for it to complete.
419 Launch a request and cancel it.
421 Launch a request with an invalid descriptor.
423 Cancel a request which is not outstanding.
425 Launch a request in OOM.
427 Launch an asynchronous request on a session and wait
431 test.Start(_L("TestAsyncSessionFunction"));
435 LaunchSessionTrebleOom();
437 // test launching async request in OOM
438 RunOomTest(LaunchSessionTrebleOom, NULL);
440 // cancel async request
441 TPckgBuf<TInt> x = 3;
443 sTestSession.Treble(x, rs);
444 sTestSession.CancelTreble();
445 User::WaitForRequest(rs);
446 test(rs == KErrCancel);
448 // bad descriptor panic
449 TestPanic(TestAsyncInvalidDescPanic, ScsImpl::EScsClBadDesc);
451 // safely cancel async request which is not queued
452 sTestSession.CancelTreble();
454 // panic if requeue outstanding request
455 TestPanic(TestRequeueOutstandingPanic, ScsImpl::EScsClAsyncAlreadyQueued);
457 // test outstanding request cancelled when session closed with RScsSessionBase::Close
458 RScsTestSession asyncSession;
459 r = asyncSession.Connect();
462 asyncSession.Treble(x, rs);
463 asyncSession.Close();
464 User::After(ScsTestImpl::KTrebleTimerDelayUs + KOneSecondUs);
465 test(rs == KErrCancel);
466 User::WaitForRequest(rs);
468 // test outstanding request not cancelled when session closed with RSessionBase::Close
469 r = asyncSession.Connect();
472 asyncSession.Treble(x, rs);
473 asyncSession.RSessionBase::Close();
474 User::After(ScsTestImpl::KTrebleTimerDelayUs + KOneSecondUs);
475 test(rs == KRequestPending); // client request not cancelled or completed
480 // -------- open / close subsession --------
483 This subsession handle is opened in OOM testing.
485 @see OpenOomSubsession
486 @see CloseOomSubsession
488 RScsTestSubsession sOomSubsession;
490 static TInt OpenOomSubsession()
492 Attempt to open a subsession in OOM.
494 @see CloseOomSubsession
498 return sOomSubsession.Create(sTestSession, 10);
501 static void CloseOomSubsession()
503 Free the subsession which was opened in OOM.
505 @see OpenOomSubsession
509 sOomSubsession.Close();
512 static void TestOpenCloseSubsession()
514 Test opening and closing a subsession, including
518 test.Start(_L("TestOpenCloseSubsession"));
522 RScsTestSubsession ss;
523 r = ss.Create(sTestSession, 10);
527 // test creating in OOM
528 RunOomTest(OpenOomSubsession, CloseOomSubsession);
533 // -------- invalid subsession function --------
535 static void TestInvalidSubsessionFunction()
537 Pass an unrecognized function to a subession and test
538 the subsession handles it properly. This tests the SCS
539 test implementation, rather than the SCS itself.
542 test.Start(_L("TestInvalidSubsessionFunction"));
544 TInt r = sTestSubsession.SendFunction(ScsTestImpl::ESubsessUnused);
545 test(r == KErrNotSupported);
550 // -------- synchronous subsession function --------
552 static void TestBadHandlePanic(RScsTestSession& aSession)
554 Call a subsession function passing in an invalid handle.
555 The current thread should be panicked.
557 @param aSession Open session to SCS test server,
558 supplied by TestPanic.
562 RScsTestSubsession ss;
563 TInt r = ss.Create(aSession, 10);
566 // modify the subsession handle
567 TUint8* addrOfHandle;
568 addrOfHandle = (TUint8*)&ss;
569 addrOfHandle += sizeof(RSessionBase);
570 *((TInt*)addrOfHandle) ^= ~0;
573 r = ss.Quadruple(x); // should be panicked with EScsClBadHandle
576 static void TestSyncSubsessionFunction()
578 Call a synchronous function on a subsession. This ensures
579 the request is routed to the subsession by the SCS. Also test
580 the SCS correctly handles an invalid subsession handle.
583 test.Start(_L("TestSyncSubsessionFunction"));
586 TInt r = sTestSubsession.Quadruple(x);
588 test(x == 4 * KSubsessValue);
590 TestPanic(TestBadHandlePanic, ScsImpl::EScsClBadHandle);
595 // -------- asynchronous subsession function --------
597 static TInt LaunchSsTrebleOom()
599 Launch an asynchronous request on a subsession in OOM.
604 TPckgBuf<TInt> x = 3;
606 sTestSubsession.Treble(x, rs);
607 User::WaitForRequest(rs);
617 static void TestAsyncSubsessionFunction()
619 Test queueing and cancelling asynchronous requests on a subsession.
622 test.Start(_L("TestAsyncSubsessionFunction"));
624 TPckgBuf<TInt> x = 7;
626 sTestSubsession.Treble(x, rs);
627 User::WaitForRequest(rs);
628 test(rs == KErrNone);
631 // test launching async request in OOM
632 RunOomTest(LaunchSsTrebleOom, NULL);
634 // cancel async request
635 sTestSubsession.Treble(x, rs);
636 sTestSubsession.CancelTreble();
637 User::WaitForRequest(rs);
638 test(rs == KErrCancel);
640 // cancel when no outstanding request
641 sTestSubsession.CancelTreble();
646 // -------- leak subsession --------
648 static void TestLeakSubsession()
650 Test closing a session with a remaining subsession;
651 ensure server does not leak memory.
654 test.Start(_L("TestLeakSubsession"));
658 sTestSession.SetServerHeapFail(KMaxTInt);
664 RScsTestSubsession ss;
665 r = ss.Create(s, KSubsessValue);
669 LetServerRun(); // 100ms, let server clean up
670 sTestSession.ResetServerHeapFail();
675 // -------- correct async requests cancelled --------
677 static void TestCorrectAsyncCancelled()
679 Test the correct requests are cancelled.
682 test.Start(_L("TestCorrectAsyncCancelled"));
690 RScsTestSubsession ss1a;
691 r = ss1a.Create(s1, KSubsessValue);
694 RScsTestSubsession ss1b;
695 r = ss1b.Create(s1, KSubsessValue);
702 RScsTestSubsession ss2a;
703 r = ss2a.Create(s2, KSubsessValue);
706 TRequestStatus r1, r1a, r1b, r2, r2a;
707 TPckgBuf<TInt> i1(10), i1a(20), i1b(30), i2(40), i2a(50);
710 ss1a.Treble(i1a, r1a);
711 ss1b.Treble(i1b, r1b);
713 ss2a.Treble(i2a, r2a);
715 test(r1 == KRequestPending);
716 test(r1a == KRequestPending);
717 test(r1b == KRequestPending);
718 test(r2 == KRequestPending);
719 test(r2a == KRequestPending);
721 ss1a.CancelTreble(); // subsession doesn't affect parent or siblings
723 test(r1 == KRequestPending);
724 test(r1a == KErrCancel);
725 test(r1b == KRequestPending);
726 test(r2 == KRequestPending);
727 test(r2a == KRequestPending);
729 s2.CancelTreble(); // session doesn't affect child
731 test(r1 == KRequestPending);
732 test(r1a == KErrCancel);
733 test(r1b == KRequestPending);
734 test(r2 == KErrCancel);
735 test(r2a == KRequestPending);
737 ss2a.Close(); // close subsession cancels outstanding request
739 test(r1 == KRequestPending);
740 test(r1a == KErrCancel);
741 test(r1b == KRequestPending);
742 test(r2 == KErrCancel);
743 test(r2a == KErrCancel);
745 // consume pending signals
746 User::WaitForRequest(r1);
747 User::WaitForRequest(r1a);
748 User::WaitForRequest(r1b);
749 User::WaitForRequest(r2);
750 User::WaitForRequest(r2a);
752 test(r1 == KErrNone);
753 test(r1a == KErrCancel);
754 test(r1b == KErrNone);
755 test(r2 == KErrCancel);
756 test(r2a == KErrCancel);
764 // -------- entrypoint --------
769 test.Title(_L("c:\\scstest.log"));
770 test.Start(_L(" @SYMTestCaseID:SEC-SCSTEST-0001 scstest "));
776 TInt r = sTestSession.Connect();
779 TestInvalidSessionFunction();
780 TestSyncSessionFunction();
781 TestAsyncSessionFunction();
783 TestOpenCloseSubsession();
785 r = sTestSubsession.Create(sTestSession, KSubsessValue);
788 TestInvalidSubsessionFunction();
789 TestSyncSubsessionFunction();
790 TestAsyncSubsessionFunction();
791 TestLeakSubsession();
792 TestCorrectAsyncCancelled();
794 sTestSubsession.Close();
795 sTestSession.ShutdownServer(); // Synchronous shutdown of server
801 void PanicIfError(TInt r)
805 User::Panic(_L("upstest failed: "), r);
812 Executable entrypoint establishes connection with SCS test server
813 and then invokes tests for each functional area.
816 // disable lazy DLL unloading so kernel heap balances at end
818 PanicIfError(l.Connect());
819 PanicIfError(l.CancelLazyDllUnload());
822 (void)test.Console();
827 // allocating a cleanup stack also installs it
828 CTrapCleanup* tc = CTrapCleanup::New();
838 // The kernel appears to leave some memory allocated related to
839 // econs.dll (maybe some sort of internal cache), which is
840 // indirectly used by the test code, so we need to ignore this
841 // allocation to allow our test to pass...
842 User::__DbgMarkEnd(TRUE,1);