sl@0: /* sl@0: * Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: * All rights reserved. sl@0: * This component and the accompanying materials are made available sl@0: * under the terms of the License "Eclipse Public License v1.0" sl@0: * which accompanies this distribution, and is available sl@0: * at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: * sl@0: * Initial Contributors: sl@0: * Nokia Corporation - initial contribution. sl@0: * sl@0: * Contributors: sl@0: * sl@0: * Description: sl@0: * Exercises the test implementation of the session count server, sl@0: * to test the base SCS functionality. sl@0: * sl@0: */ sl@0: sl@0: sl@0: /** sl@0: @file sl@0: */ sl@0: sl@0: sl@0: #include sl@0: #include sl@0: #include sl@0: #include "rtestwrapper.h" sl@0: #include sl@0: sl@0: #include sl@0: #include "scstestcommon.h" sl@0: #include "scstestclient.h" sl@0: sl@0: const TInt KOneSecondUs = 1000 * 1000; ///< One second in microseconds. sl@0: sl@0: /** Top-level test object renders stages and confirms conditions. */ sl@0: static RTestWrapper test(_L("SCSTEST")); sl@0: sl@0: /** sl@0: This session handle is defined at the file level so each individual test sl@0: does not have to connect to the server. sl@0: */ sl@0: static RScsTestSession sTestSession; sl@0: /** sl@0: This subsession handle is defined at the file level so each individual test sl@0: does not have to connect to the server and create a subssesion. sl@0: */ sl@0: static RScsTestSubsession sTestSubsession; sl@0: sl@0: /** Arbitrary integer value used to construct subsession. */ sl@0: static const TInt KSubsessValue = 10; sl@0: sl@0: static void LetServerRun() sl@0: /** sl@0: Sleep for 100ms so the server thread can run to clean up, sl@0: terminate, or just process the last request which it was sent. sl@0: */ sl@0: { sl@0: User::After(100 * 1000); sl@0: } sl@0: sl@0: // -------- OOM testing -------- sl@0: sl@0: static void RunOomTest(TInt (*aAllocFunc)(), void (*aFreeFunc)()) sl@0: /** sl@0: Run the supplied allocator function while forcing OOM on the server side. sl@0: On failure, this functions tests that the server heap is balanced. On sl@0: success, it runs the free function and also tests that the server heap is sl@0: balanced. sl@0: sl@0: @param aAllocFunc Function which allocates resources on the server heap. sl@0: @param aFreeFunc Frees the resources allocated with aAllocFunc. It should sl@0: only be necessary to call this function if aAllocFunc sl@0: succeeds. This argument can be NULL if there is no sl@0: corresponding free function. sl@0: */ sl@0: { sl@0: TInt r = KErrNoMemory; sl@0: sl@0: for (TInt i = 1; r == KErrNoMemory; ++i) sl@0: { sl@0: sTestSession.SetServerHeapFail(i); sl@0: sl@0: r = aAllocFunc(); sl@0: sl@0: test(r == KErrNone || r == KErrNoMemory); sl@0: if (r == KErrNone && aFreeFunc != NULL) sl@0: aFreeFunc(); sl@0: sl@0: sTestSession.ResetServerHeapFail(); sl@0: } sl@0: } sl@0: sl@0: // -------- panic testing -------- sl@0: sl@0: /** sl@0: To test that a client is panicked, pass a function with this sl@0: signature to TestPanic. It will be called from a new thread. sl@0: sl@0: @see TestPanic sl@0: */ sl@0: typedef void (*TPanicFunc)(RScsTestSession&); sl@0: sl@0: static void ConfirmPanicReason(RThread aThread, TInt aExpectedReason) sl@0: /** sl@0: Test the supplied thread was panicked with category sl@0: ScsImpl::KScsClientPanicCat and the supplied reason. sl@0: sl@0: @param aThread Panicked thread. sl@0: @param aExpectedReason The thread should have been panicked with sl@0: this reason. sl@0: @see ScsImpl::KScsClientPanicCat sl@0: */ sl@0: { sl@0: TExitType exitType = aThread.ExitType(); sl@0: TExitCategoryName exitCat = aThread.ExitCategory(); sl@0: TInt exitReason = aThread.ExitReason(); sl@0: sl@0: test(exitType == EExitPanic); sl@0: test(exitCat == ScsImpl::KScsClientPanicCat); sl@0: test(exitReason == aExpectedReason); sl@0: } sl@0: sl@0: static TInt TestPanicEntrypoint(TAny* aPtr) sl@0: /** sl@0: This entrypoint is called by the panic thread. The sl@0: function connects to the SCS test server and passes sl@0: the handle to the function that should be panicked. sl@0: sl@0: @param aPtr Standard entrypoint argument. This is actually sl@0: a pointer to the function to call with the connected sl@0: session. sl@0: @return KErrNone. Required to satisfy entrypoint signature. sl@0: */ sl@0: { sl@0: RScsTestSession s; sl@0: TInt r = s.Connect(); sl@0: test(r == KErrNone); sl@0: sl@0: TPanicFunc f = TAnyPtrToFuncPtr(aPtr); sl@0: f(s); sl@0: sl@0: test(EFalse); // should not reach here sl@0: return KErrNone; sl@0: } sl@0: sl@0: static void TestPanic(TPanicFunc aFunc, TInt aExpectedReason) sl@0: /** sl@0: Create a thread which should be panicked because it will sl@0: pass invalid data to the SCS test server. Test the thread sl@0: is panicked with the expected category and reason. sl@0: sl@0: @param aFunc Function to call from panic thread. sl@0: @param aExpectedReason Reason with which the thread should sl@0: be panicked. sl@0: */ sl@0: { sl@0: RThread thd; sl@0: TInt r = thd.Create( sl@0: _L("ScsTestPanic"), TestPanicEntrypoint, sl@0: KDefaultStackSize, KMinHeapSize, KMinHeapSize, (TAny*) aFunc); sl@0: test(r == KErrNone); sl@0: sl@0: TRequestStatus rs; sl@0: thd.Rendezvous(rs); sl@0: test(rs == KRequestPending); sl@0: TBool jit = User::JustInTime(); sl@0: User::SetJustInTime(EFalse); sl@0: thd.Resume(); sl@0: sl@0: User::WaitForRequest(rs); sl@0: User::SetJustInTime(jit); sl@0: ConfirmPanicReason(thd, aExpectedReason); sl@0: thd.Close(); sl@0: } sl@0: sl@0: // -------- open / close -------- sl@0: sl@0: /** Handle to a session which the test code attempts to open in server-side OOM. */ sl@0: RScsTestSession sOomTestSession; sl@0: sl@0: static TInt OpenOomSession() sl@0: /** sl@0: This function is invoked by RunOomTest. It just sl@0: attempts to connect to the SCS test server. sl@0: sl@0: @return Return code from RScsTestSession::Connect. sl@0: @see CloseOomSession sl@0: */ sl@0: { sl@0: return sOomTestSession.Connect(); sl@0: } sl@0: sl@0: static void CloseOomSession() sl@0: /** sl@0: Closes the session which was opened by OpenOomSession. sl@0: sl@0: @see OpenOomSession sl@0: @pre OpenOomSession was successfully opened by OpenOomSession. sl@0: */ sl@0: { sl@0: sOomTestSession.Close(); sl@0: } sl@0: sl@0: static void TestServerDeath() sl@0: { sl@0: test.Start(_L("TestServerDeath")); sl@0: sl@0: test.Next(_L("Starting server without shutdown timer")); sl@0: // Create marker file to get server to run without a activity timeout sl@0: RFs fs; sl@0: TInt r = fs.Connect(); sl@0: test(r == KErrNone); sl@0: (void) fs.Delete(KDisableScsTestServerTimeout()); sl@0: sl@0: RFile file; sl@0: r = file.Create(fs, KDisableScsTestServerTimeout(), EFileShareAny|EFileWrite); sl@0: test(r == KErrNone); sl@0: file.Close(); sl@0: sl@0: // Start server sl@0: RScsTestSession scsts; sl@0: r = scsts.Connect(); sl@0: test(r == KErrNone); sl@0: sl@0: test.Next(_L("Checking ShutdownServer is not allowed")); sl@0: r = scsts.ShutdownServer(); sl@0: test(r == KErrNotSupported); sl@0: sl@0: sl@0: test.Next(_L("Doing an async call to check server does not attempt to restart the timer and crash")); sl@0: TPckgBuf x1 = 1; sl@0: TRequestStatus rs1; sl@0: scsts.Treble(x1, rs1); sl@0: User::WaitForRequest(rs1); sl@0: sl@0: test.Printf(_L("NukeServer - scstestserver.exe SHOULD panic\n")); sl@0: r = scsts.NukeServer(); sl@0: test(r == KErrServerTerminated); sl@0: sl@0: sl@0: (void) fs.Delete(KDisableScsTestServerTimeout()); sl@0: fs.Close(); sl@0: scsts.Close(); sl@0: test.End(); sl@0: } sl@0: sl@0: static void TestOpenClose() sl@0: /** sl@0: Attempt to connect to the server when supplying default, sl@0: lower, and higher version numbers. Attempt to open a session sl@0: in server-side OOM. sl@0: */ sl@0: { sl@0: test.Start(_L("TestOpenClose")); sl@0: sl@0: TInt r; sl@0: RScsTestSession scsts; sl@0: sl@0: // default version sl@0: r = scsts.Connect(); sl@0: test(r == KErrNone); sl@0: scsts.Close(); sl@0: sl@0: // lower-than-supported version sl@0: TVersion v = ScsTestImpl::Version(); sl@0: --v.iMajor; sl@0: r = scsts.Connect(v); sl@0: test(r == KErrNone); sl@0: scsts.Close(); sl@0: sl@0: // supported version (should be same as default) sl@0: ++v.iMajor; sl@0: r = scsts.Connect(v); sl@0: test(r == KErrNone); sl@0: scsts.Close(); sl@0: sl@0: // greater-than-supported version sl@0: ++v.iMajor; sl@0: r = scsts.Connect(v); sl@0: test(r == KErrNotSupported); sl@0: sl@0: // test opening session when server running out of memory sl@0: r = sTestSession.Connect(); // required to send OOM commands sl@0: test(r == KErrNone); sl@0: sl@0: RunOomTest(OpenOomSession, CloseOomSession); sl@0: sl@0: sTestSession.Close(); sl@0: sl@0: #if 0 sl@0: // Test closing server with an out standing request sl@0: r = scsts.Connect(); sl@0: test(r == KErrNone); sl@0: test(r == KErrNone); sl@0: TPckgBuf x1 = 1; sl@0: TRequestStatus rs1; sl@0: scsts.Treble(x1, rs1); sl@0: // Bypass the presession close sl@0: RSessionBase *session = &scsts; sl@0: session->Close(); sl@0: User::WaitForRequest(rs1); sl@0: test(rs1 == KErrCancel); sl@0: #endif sl@0: sl@0: test.End(); sl@0: } sl@0: sl@0: // -------- invalid session function -------- sl@0: sl@0: static void TestInvalidSessionFunction() sl@0: /** sl@0: Send an unrecognized SCS code and confirm that it is sl@0: rejected with KErrNotSupported. This tests the SCS sl@0: implementation. sl@0: sl@0: Send an unrecognized function identifier to the session sl@0: and confirm that it is also rejected with KErrNotSupported. sl@0: This tests the test server session implementation. sl@0: */ sl@0: { sl@0: test.Start(_L("TestInvalidSessionFunction")); sl@0: sl@0: TInt r; sl@0: sl@0: r = sTestSession.SendCustomFunction(ScsImpl::EScsUnused); sl@0: test(r == KErrNotSupported); sl@0: sl@0: r = sTestSession.SendCustomFunction(ScsImpl::ECallSessionFunc | ScsTestImpl::ESessUnused); sl@0: test(r == KErrNotSupported); sl@0: sl@0: test.End(); sl@0: } sl@0: sl@0: // -------- synchronous session function -------- sl@0: sl@0: static void TestSyncSessionFunction() sl@0: /** sl@0: Send a recognized function to the SCS test session, sl@0: and confirm that it is executed correctly. sl@0: */ sl@0: { sl@0: test.Start(_L("TestSyncSessionFunction")); sl@0: sl@0: TInt x = 3; sl@0: TInt r = sTestSession.Double(x); sl@0: test(r == KErrNone); sl@0: test(x == 6); sl@0: sl@0: test.End(); sl@0: } sl@0: sl@0: // -------- asynchronous session function -------- sl@0: sl@0: static TInt LaunchSessionTrebleOom() sl@0: /** sl@0: Attempt to launch an asynchronous command on a session sl@0: under OOM conditions. sl@0: */ sl@0: { sl@0: TPckgBuf x = 3; sl@0: TRequestStatus rs; sl@0: sTestSession.Treble(x, rs); sl@0: User::WaitForRequest(rs); sl@0: sl@0: if (rs == KErrNone) sl@0: { sl@0: test(x() == 9); sl@0: } sl@0: sl@0: return rs.Int(); sl@0: } sl@0: sl@0: static void TestAsyncInvalidDescPanic(RScsTestSession& aSession) sl@0: /** sl@0: Pass an invalid descriptor to the SCS test server. sl@0: The current thread should be panicked. sl@0: sl@0: @param aSession Open session to SCS test server, sl@0: supplied by TestPanic. sl@0: @see TestPanic sl@0: */ sl@0: { sl@0: TDes8* nullDes8 = 0; sl@0: TRequestStatus rs; sl@0: aSession.Treble(*nullDes8, rs); sl@0: User::WaitForRequest(rs); sl@0: } sl@0: sl@0: static void TestRequeueOutstandingPanic(RScsTestSession& aSession) sl@0: /** sl@0: Attempt to requeue an asynchronous request which is still sl@0: outstanding. The current thread should be panicked. sl@0: sl@0: @param aSession Connected session to SCS test server. sl@0: @see TestPanic sl@0: */ sl@0: { sl@0: TPckgBuf x1 = 1; sl@0: TRequestStatus rs1; sl@0: aSession.Treble(x1, rs1); sl@0: sl@0: TPckgBuf x2 = 2; sl@0: TRequestStatus rs2; sl@0: aSession.Treble(x2, rs2); sl@0: sl@0: User::WaitForRequest(rs1, rs2); sl@0: User::WaitForRequest(rs1, rs2); sl@0: } sl@0: sl@0: static void TestAsyncSessionFunction() sl@0: /** sl@0: Test asynchronous session-relative functions. sl@0: sl@0: Launch a request and wait for it to complete. sl@0: sl@0: Launch a request and cancel it. sl@0: sl@0: Launch a request with an invalid descriptor. sl@0: sl@0: Cancel a request which is not outstanding. sl@0: sl@0: Launch a request in OOM. sl@0: sl@0: Launch an asynchronous request on a session and wait sl@0: for it to complete. sl@0: */ sl@0: { sl@0: test.Start(_L("TestAsyncSessionFunction")); sl@0: sl@0: TInt r; sl@0: sl@0: LaunchSessionTrebleOom(); sl@0: sl@0: // test launching async request in OOM sl@0: RunOomTest(LaunchSessionTrebleOom, NULL); sl@0: sl@0: // cancel async request sl@0: TPckgBuf x = 3; sl@0: TRequestStatus rs; sl@0: sTestSession.Treble(x, rs); sl@0: sTestSession.CancelTreble(); sl@0: User::WaitForRequest(rs); sl@0: test(rs == KErrCancel); sl@0: sl@0: // bad descriptor panic sl@0: TestPanic(TestAsyncInvalidDescPanic, ScsImpl::EScsClBadDesc); sl@0: sl@0: // safely cancel async request which is not queued sl@0: sTestSession.CancelTreble(); sl@0: sl@0: // panic if requeue outstanding request sl@0: TestPanic(TestRequeueOutstandingPanic, ScsImpl::EScsClAsyncAlreadyQueued); sl@0: sl@0: // test outstanding request cancelled when session closed with RScsSessionBase::Close sl@0: RScsTestSession asyncSession; sl@0: r = asyncSession.Connect(); sl@0: test(r == KErrNone); sl@0: x() = 4; sl@0: asyncSession.Treble(x, rs); sl@0: asyncSession.Close(); sl@0: User::After(ScsTestImpl::KTrebleTimerDelayUs + KOneSecondUs); sl@0: test(rs == KErrCancel); sl@0: User::WaitForRequest(rs); sl@0: sl@0: // test outstanding request not cancelled when session closed with RSessionBase::Close sl@0: r = asyncSession.Connect(); sl@0: test(r == KErrNone); sl@0: x() = 4; sl@0: asyncSession.Treble(x, rs); sl@0: asyncSession.RSessionBase::Close(); sl@0: User::After(ScsTestImpl::KTrebleTimerDelayUs + KOneSecondUs); sl@0: test(rs == KRequestPending); // client request not cancelled or completed sl@0: sl@0: test.End(); sl@0: } sl@0: sl@0: // -------- open / close subsession -------- sl@0: sl@0: /** sl@0: This subsession handle is opened in OOM testing. sl@0: sl@0: @see OpenOomSubsession sl@0: @see CloseOomSubsession sl@0: */ sl@0: RScsTestSubsession sOomSubsession; sl@0: sl@0: static TInt OpenOomSubsession() sl@0: /** sl@0: Attempt to open a subsession in OOM. sl@0: sl@0: @see CloseOomSubsession sl@0: @see RunOomTest sl@0: */ sl@0: { sl@0: return sOomSubsession.Create(sTestSession, 10); sl@0: } sl@0: sl@0: static void CloseOomSubsession() sl@0: /** sl@0: Free the subsession which was opened in OOM. sl@0: sl@0: @see OpenOomSubsession sl@0: @see RunOomTest sl@0: */ sl@0: { sl@0: sOomSubsession.Close(); sl@0: } sl@0: sl@0: static void TestOpenCloseSubsession() sl@0: /** sl@0: Test opening and closing a subsession, including sl@0: opening in OOM. sl@0: */ sl@0: { sl@0: test.Start(_L("TestOpenCloseSubsession")); sl@0: sl@0: TInt r; sl@0: sl@0: RScsTestSubsession ss; sl@0: r = ss.Create(sTestSession, 10); sl@0: test(r == KErrNone); sl@0: ss.Close(); sl@0: sl@0: // test creating in OOM sl@0: RunOomTest(OpenOomSubsession, CloseOomSubsession); sl@0: sl@0: test.End(); sl@0: } sl@0: sl@0: // -------- invalid subsession function -------- sl@0: sl@0: static void TestInvalidSubsessionFunction() sl@0: /** sl@0: Pass an unrecognized function to a subession and test sl@0: the subsession handles it properly. This tests the SCS sl@0: test implementation, rather than the SCS itself. sl@0: */ sl@0: { sl@0: test.Start(_L("TestInvalidSubsessionFunction")); sl@0: sl@0: TInt r = sTestSubsession.SendFunction(ScsTestImpl::ESubsessUnused); sl@0: test(r == KErrNotSupported); sl@0: sl@0: test.End(); sl@0: } sl@0: sl@0: // -------- synchronous subsession function -------- sl@0: sl@0: static void TestBadHandlePanic(RScsTestSession& aSession) sl@0: /** sl@0: Call a subsession function passing in an invalid handle. sl@0: The current thread should be panicked. sl@0: sl@0: @param aSession Open session to SCS test server, sl@0: supplied by TestPanic. sl@0: @see TestPanic sl@0: */ sl@0: { sl@0: RScsTestSubsession ss; sl@0: TInt r = ss.Create(aSession, 10); sl@0: test(r == KErrNone); sl@0: sl@0: // modify the subsession handle sl@0: TUint8* addrOfHandle; sl@0: addrOfHandle = (TUint8*)&ss; sl@0: addrOfHandle += sizeof(RSessionBase); sl@0: *((TInt*)addrOfHandle) ^= ~0; sl@0: sl@0: TInt x = 3; sl@0: r = ss.Quadruple(x); // should be panicked with EScsClBadHandle sl@0: } sl@0: sl@0: static void TestSyncSubsessionFunction() sl@0: /** sl@0: Call a synchronous function on a subsession. This ensures sl@0: the request is routed to the subsession by the SCS. Also test sl@0: the SCS correctly handles an invalid subsession handle. sl@0: */ sl@0: { sl@0: test.Start(_L("TestSyncSubsessionFunction")); sl@0: sl@0: TInt x = -1; sl@0: TInt r = sTestSubsession.Quadruple(x); sl@0: test(r == KErrNone); sl@0: test(x == 4 * KSubsessValue); sl@0: sl@0: TestPanic(TestBadHandlePanic, ScsImpl::EScsClBadHandle); sl@0: sl@0: test.End(); sl@0: } sl@0: sl@0: // -------- asynchronous subsession function -------- sl@0: sl@0: static TInt LaunchSsTrebleOom() sl@0: /** sl@0: Launch an asynchronous request on a subsession in OOM. sl@0: sl@0: @see RunOomTest sl@0: */ sl@0: { sl@0: TPckgBuf x = 3; sl@0: TRequestStatus rs; sl@0: sTestSubsession.Treble(x, rs); sl@0: User::WaitForRequest(rs); sl@0: sl@0: if (rs == KErrNone) sl@0: { sl@0: test(x() == 9); sl@0: } sl@0: sl@0: return rs.Int(); sl@0: } sl@0: sl@0: static void TestAsyncSubsessionFunction() sl@0: /** sl@0: Test queueing and cancelling asynchronous requests on a subsession. sl@0: */ sl@0: { sl@0: test.Start(_L("TestAsyncSubsessionFunction")); sl@0: sl@0: TPckgBuf x = 7; sl@0: TRequestStatus rs; sl@0: sTestSubsession.Treble(x, rs); sl@0: User::WaitForRequest(rs); sl@0: test(rs == KErrNone); sl@0: test(x() == 21); sl@0: sl@0: // test launching async request in OOM sl@0: RunOomTest(LaunchSsTrebleOom, NULL); sl@0: sl@0: // cancel async request sl@0: sTestSubsession.Treble(x, rs); sl@0: sTestSubsession.CancelTreble(); sl@0: User::WaitForRequest(rs); sl@0: test(rs == KErrCancel); sl@0: sl@0: // cancel when no outstanding request sl@0: sTestSubsession.CancelTreble(); sl@0: sl@0: test.End(); sl@0: } sl@0: sl@0: // -------- leak subsession -------- sl@0: sl@0: static void TestLeakSubsession() sl@0: /** sl@0: Test closing a session with a remaining subsession; sl@0: ensure server does not leak memory. sl@0: */ sl@0: { sl@0: test.Start(_L("TestLeakSubsession")); sl@0: sl@0: TInt r; sl@0: sl@0: sTestSession.SetServerHeapFail(KMaxTInt); sl@0: sl@0: RScsTestSession s; sl@0: r = s.Connect(); sl@0: test(r == KErrNone); sl@0: sl@0: RScsTestSubsession ss; sl@0: r = ss.Create(s, KSubsessValue); sl@0: test(r == KErrNone); sl@0: sl@0: s.Close(); sl@0: LetServerRun(); // 100ms, let server clean up sl@0: sTestSession.ResetServerHeapFail(); sl@0: sl@0: test.End(); sl@0: } sl@0: sl@0: // -------- correct async requests cancelled -------- sl@0: sl@0: static void TestCorrectAsyncCancelled() sl@0: /** sl@0: Test the correct requests are cancelled. sl@0: */ sl@0: { sl@0: test.Start(_L("TestCorrectAsyncCancelled")); sl@0: sl@0: TInt r; sl@0: sl@0: RScsTestSession s1; sl@0: r = s1.Connect(); sl@0: test(r == KErrNone); sl@0: sl@0: RScsTestSubsession ss1a; sl@0: r = ss1a.Create(s1, KSubsessValue); sl@0: test(r == KErrNone); sl@0: sl@0: RScsTestSubsession ss1b; sl@0: r = ss1b.Create(s1, KSubsessValue); sl@0: test(r == KErrNone); sl@0: sl@0: RScsTestSession s2; sl@0: r = s2.Connect(); sl@0: test(r == KErrNone); sl@0: sl@0: RScsTestSubsession ss2a; sl@0: r = ss2a.Create(s2, KSubsessValue); sl@0: test(r == KErrNone); sl@0: sl@0: TRequestStatus r1, r1a, r1b, r2, r2a; sl@0: TPckgBuf i1(10), i1a(20), i1b(30), i2(40), i2a(50); sl@0: sl@0: s1.Treble(i1, r1); sl@0: ss1a.Treble(i1a, r1a); sl@0: ss1b.Treble(i1b, r1b); sl@0: s2.Treble(i2, r2); sl@0: ss2a.Treble(i2a, r2a); sl@0: sl@0: test(r1 == KRequestPending); sl@0: test(r1a == KRequestPending); sl@0: test(r1b == KRequestPending); sl@0: test(r2 == KRequestPending); sl@0: test(r2a == KRequestPending); sl@0: sl@0: ss1a.CancelTreble(); // subsession doesn't affect parent or siblings sl@0: LetServerRun(); sl@0: test(r1 == KRequestPending); sl@0: test(r1a == KErrCancel); sl@0: test(r1b == KRequestPending); sl@0: test(r2 == KRequestPending); sl@0: test(r2a == KRequestPending); sl@0: sl@0: s2.CancelTreble(); // session doesn't affect child sl@0: LetServerRun(); sl@0: test(r1 == KRequestPending); sl@0: test(r1a == KErrCancel); sl@0: test(r1b == KRequestPending); sl@0: test(r2 == KErrCancel); sl@0: test(r2a == KRequestPending); sl@0: sl@0: ss2a.Close(); // close subsession cancels outstanding request sl@0: LetServerRun(); sl@0: test(r1 == KRequestPending); sl@0: test(r1a == KErrCancel); sl@0: test(r1b == KRequestPending); sl@0: test(r2 == KErrCancel); sl@0: test(r2a == KErrCancel); sl@0: sl@0: // consume pending signals sl@0: User::WaitForRequest(r1); sl@0: User::WaitForRequest(r1a); sl@0: User::WaitForRequest(r1b); sl@0: User::WaitForRequest(r2); sl@0: User::WaitForRequest(r2a); sl@0: sl@0: test(r1 == KErrNone); sl@0: test(r1a == KErrCancel); sl@0: test(r1b == KErrNone); sl@0: test(r2 == KErrCancel); sl@0: test(r2a == KErrCancel); sl@0: sl@0: s1.Close(); sl@0: s2.Close(); sl@0: sl@0: test.End(); sl@0: } sl@0: sl@0: // -------- entrypoint -------- sl@0: sl@0: sl@0: void MainL() sl@0: { sl@0: test.Title(_L("c:\\scstest.log")); sl@0: test.Start(_L(" @SYMTestCaseID:SEC-SCSTEST-0001 scstest ")); sl@0: sl@0: TestServerDeath(); sl@0: sl@0: TestOpenClose(); sl@0: sl@0: TInt r = sTestSession.Connect(); sl@0: test(r == KErrNone); sl@0: sl@0: TestInvalidSessionFunction(); sl@0: TestSyncSessionFunction(); sl@0: TestAsyncSessionFunction(); sl@0: sl@0: TestOpenCloseSubsession(); sl@0: sl@0: r = sTestSubsession.Create(sTestSession, KSubsessValue); sl@0: test(r == KErrNone); sl@0: sl@0: TestInvalidSubsessionFunction(); sl@0: TestSyncSubsessionFunction(); sl@0: TestAsyncSubsessionFunction(); sl@0: TestLeakSubsession(); sl@0: TestCorrectAsyncCancelled(); sl@0: sl@0: sTestSubsession.Close(); sl@0: sTestSession.ShutdownServer(); // Synchronous shutdown of server sl@0: sl@0: test.End(); sl@0: test.Close(); sl@0: } sl@0: sl@0: void PanicIfError(TInt r) sl@0: { sl@0: if(r != KErrNone) sl@0: { sl@0: User::Panic(_L("upstest failed: "), r); sl@0: } sl@0: } sl@0: sl@0: sl@0: TInt E32Main() sl@0: /** sl@0: Executable entrypoint establishes connection with SCS test server sl@0: and then invokes tests for each functional area. sl@0: */ sl@0: { sl@0: // disable lazy DLL unloading so kernel heap balances at end sl@0: RLoader l; sl@0: PanicIfError(l.Connect()); sl@0: PanicIfError(l.CancelLazyDllUnload()); sl@0: l.Close(); sl@0: sl@0: (void)test.Console(); sl@0: sl@0: __UHEAP_MARK; sl@0: __KHEAP_MARK; sl@0: sl@0: // allocating a cleanup stack also installs it sl@0: CTrapCleanup* tc = CTrapCleanup::New(); sl@0: if (tc == 0) sl@0: return KErrNoMemory; sl@0: sl@0: TRAPD(err, MainL()); sl@0: PanicIfError(err); sl@0: sl@0: sl@0: delete tc; sl@0: sl@0: // The kernel appears to leave some memory allocated related to sl@0: // econs.dll (maybe some sort of internal cache), which is sl@0: // indirectly used by the test code, so we need to ignore this sl@0: // allocation to allow our test to pass... sl@0: User::__DbgMarkEnd(TRUE,1); sl@0: __UHEAP_MARKEND; sl@0: sl@0: sl@0: return KErrNone; sl@0: } sl@0: sl@0: sl@0: // End of file