diff -r 000000000000 -r a41df078684a kerneltest/e32test/system/t_svr_connect.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kerneltest/e32test/system/t_svr_connect.cpp Mon Oct 19 15:55:17 2009 +0100 @@ -0,0 +1,915 @@ +// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of the License "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// e32test\system\t_svr_connect.cpp +// Overview: +// Tests correct operation of server when interleaving connect/disconnect/ +// other messages and creating the user-side session object (setting the +// session cookie) in interesting manners. +// Tests that clients/servers are panicked when performing illegal operations +// w.r.t. server connection, i.e. a client thread may not send more than one +// connect message simultaneously, nor may it send another connect message +// once a connect message has been successfully completed. Similarly, a server +// may not set the cookie twice nor may it set the cookie to be NULL. Also, a +// server may only set the cookie from a connect message and from no other. +// API Information: +// RServer2 +// Details: +// - Test asynchronous server connect in various ways. Verify results +// are as expected. +// - Test illegal client/server behaviour. Verify threads are panicked, +// as expected. +// Platforms/Drives/Compatibility: +// All. +// Assumptions/Requirement/Pre-requisites: +// None. +// Failures and causes: +// Failure of this test would be caused by an incorrect modification of +// the internal client/server mechanism in the kernel. +// Base Port information: +// This is a unit test of the client/server mechanism within the kernel. +// It should be invariant to base ports. If the kernel proper has not been +// modified, this test should not fail with any new base port. +// +// + +#include +#include "../misc/int_svr_calls.h" +#include + +_LIT(KTestName, "t_svr_connect"); +LOCAL_D RTest test(KTestName); +LOCAL_D RTest test_client(KTestName); +LOCAL_D RTest test_server(KTestName); + +_LIT(KServerName, "t_svr_connect"); +_LIT8(KServerName8, "t_svr_connect"); +_LIT(KMainThread, "main thread"); +_LIT(KServerThread, "server thread"); +_LIT(KClientThread, "client thread"); +_LIT(KClientThread2, "client thread2"); +_LIT(KClientThread3, "client thread3"); + +class RTestServer : public RSessionBase + { +public: + inline static TInt CreateSession(TInt aMsgSlots) { return SessionCreate(KServerName8,aMsgSlots,NULL,EIpcSession_Sharable); } + }; + +// Messages to send: +// +// connect, 1 +// a.n.other, 2 +// disconnect 3 +// +// Things to do in the server: +// +// recieve connect 4 +// set cookie 5 +// complete connect 6 +// receive a.n.other 7 +// complete a.n.other 8 +// receive disconnect 9 +// complete disconnect 10 +// + +enum TMsgType + { + EConnect = -1, + EDisConnect = -2, + EANOther = 1, + EANOther2 = 2, + EMsgCount = 4 + }; + +enum TServerControl + { + EReceiveMsg = 0, + EReceiveBlocked = 1, + EWaitForReceive = 2, + ESetCookie = 3, + ESetNullCookie = 4, + ECompleteMsg = 5, + EServerDie = 6 + }; + +enum TClientControl + { + ESendMsg = 0, + EWaitMsg = 1, + ECreateSession = 2, + EClientDie = 3, + ESetCritical = 4 + }; + +static TMsgType TheMsgType; +static TServerControl TheServerControl; +static TClientControl TheClientControl; +static RSemaphore ServerSemaphore; +static RSemaphore ClientSemaphore; +static RSemaphore TaskCompletionSemaphore; +static RMessage2 Msgs[EMsgCount]; +static RServer2 Server; +static RThread ServerThread; +static RThread ClientThread; +static RTestServer ServerHandle; +static TRequestStatus ConnectStatus; +static TRequestStatus ANOtherStatus; +static TRequestStatus ANOther2Status; +static TRequestStatus ServerReceiveStatus; +static TInt TheNumberOfMsgSlots; +static TInt ErrorExpected; +static User::TCritical CriticalLevel; + + +static const TAny* const KSessionCookie = (const TAny*)0x12345; +static TRequestStatus* volatile KNullReference = 0; + +void DoServerAction(); +void DoClientAction(); +TInt Index(); + +TInt TestThreadServer(TAny*) + { + test_server(Server.CreateGlobal(KServerName) == KErrNone); + RThread::Rendezvous(KErrNone); + + for (;;) + { + ServerSemaphore.Wait(); + DoServerAction(); + TaskCompletionSemaphore.Signal(); + } + } + +TInt Index() + { + switch (TheMsgType) + { + case EConnect: + return 0; + case EDisConnect: + return 3; + case EANOther: + return 1; + case EANOther2: + return 2; + default: + return -1; + }; + } + +TRequestStatus& RequestStatus() + { + switch (TheMsgType) + { + case EConnect: + return ConnectStatus; + case EANOther: + return ANOtherStatus; + case EANOther2: + return ANOther2Status; + default: + User::Invariant(); + }; + return *(TRequestStatus*)KNullReference; + } + +void DoServerAction() + { + switch (TheServerControl) + { + case EReceiveMsg: + { + RMessage2& msg = Msgs[Index()]; + Server.Receive(msg); + test_server(msg.Function() == TheMsgType); + } + break; + case EReceiveBlocked: + { + RMessage2& msg = Msgs[Index()]; + Server.Receive(msg, ServerReceiveStatus); + test_server(ServerReceiveStatus.Int() == KRequestPending); + } + break; + case EWaitForReceive: + { + User::WaitForRequest(ServerReceiveStatus); + test_server(ServerReceiveStatus.Int() == KErrNone); + test_server(Msgs[Index()].Function() == TheMsgType); + } + break; + case ESetCookie: + { + SetSessionPtr(Msgs[Index()].Handle(), KSessionCookie); + } + break; + case ESetNullCookie: + { + SetSessionPtr(Msgs[Index()].Handle(), NULL); + } + break; + case ECompleteMsg: + { + Msgs[Index()].Complete(KErrNone); + } + break; + case EServerDie: + { + User::Exit(0); + } + break; + default: + { + } + break; + }; + } + +void StartServer() + { + ServerThread.Create(KServerThread, TestThreadServer, KDefaultStackSize, 4096, 4096, NULL); + + TRequestStatus started; + ServerThread.Rendezvous(started); + + ServerThread.Resume(); + User::WaitForRequest(started); + + test(started.Int() == KErrNone); + } + +void StopServer() + { + TRequestStatus logon; + ServerThread.Logon(logon); + + TheServerControl = EServerDie; + ServerSemaphore.Signal(); + + User::WaitForRequest(logon); + test(logon.Int() == KErrNone); + + CLOSE_AND_WAIT(ServerThread); + } + +TInt TestThreadClient(TAny*) + { + RThread::Rendezvous(KErrNone); + + for (;;) + { + ClientSemaphore.Wait(); + DoClientAction(); + TaskCompletionSemaphore.Signal(); + } + } + +void DoClientAction() + { + switch (TheClientControl) + { + case ESendMsg: + { + if (TheMsgType == EDisConnect) + ServerHandle.Close(); + else + SessionSend(ServerHandle.Handle(), TheMsgType, NULL, &RequestStatus()); + } + break; + case EWaitMsg: + { + User::WaitForRequest(RequestStatus()); + } + break; + case ECreateSession: + { + TInt err = ServerHandle.SetReturnedHandle(RTestServer::CreateSession(TheNumberOfMsgSlots)); + + if (err != ErrorExpected) + { + test_client.Printf(_L("Error returned = %d\n"),err); + test_client(EFalse,__LINE__); + } + } + break; + case EClientDie: + { + User::SetCritical(User::ENotCritical); + User::Exit(0); + } + break; + case ESetCritical: + { + User::SetCritical(CriticalLevel); + break; + } + default: + { + } + break; + }; + } + +// I'm lazy and I haven't completed all the IPC the client thread does, +// so even when the client thread panics, the DObject is still kept alive +// until the server goes away. Therefore if I want another client I rename. +void StartClient(const TDesC& aName) + { + ClientThread.Create(aName, TestThreadClient, KDefaultStackSize, 4096, 4096, NULL); + + TRequestStatus started; + ClientThread.Rendezvous(started); + + ClientThread.Resume(); + User::WaitForRequest(started); + + test(started.Int() == KErrNone); + } + +void StartClient() + { + StartClient(KClientThread); + } + +void StopClient() + { + TRequestStatus logon; + ClientThread.Logon(logon); + + TheClientControl = EClientDie; + ClientSemaphore.Signal(); + + User::WaitForRequest(logon); + test(logon.Int() == KErrNone); + + CLOSE_AND_WAIT(ClientThread); + } + +void CreateSemaphores() + { + TInt err = ServerSemaphore.CreateLocal(0); + test(err == KErrNone); + err = ClientSemaphore.CreateLocal(0); + test(err == KErrNone); + err = TaskCompletionSemaphore.CreateLocal(0); + test(err == KErrNone); + } + +void CloseSemaphores() + { + ServerSemaphore.Close(); + ClientSemaphore.Close(); + TaskCompletionSemaphore.Close(); + } + +void CreateSession(TInt aErrorExpected=KErrNone, TInt aMsgSlots=-1) + { + TheClientControl = ECreateSession; + TheNumberOfMsgSlots = aMsgSlots; + ErrorExpected=aErrorExpected; + ClientSemaphore.Signal(); + TaskCompletionSemaphore.Wait(); + } + +void SendMsg(TMsgType aType) + { + TheClientControl = ESendMsg; + TheMsgType = aType; + ClientSemaphore.Signal(); + TaskCompletionSemaphore.Wait(); + } + +void SendMsg_NoWait(TMsgType aType) + { + TheClientControl = ESendMsg; + TheMsgType = aType; + ClientSemaphore.Signal(); + } + +void WaitMsg(TMsgType aType) + { + TheClientControl = EWaitMsg; + TheMsgType = aType; + ClientSemaphore.Signal(); + TaskCompletionSemaphore.Wait(); + } + +void ReceiveBlocked(TMsgType aType) + { + TheServerControl = EReceiveBlocked; + TheMsgType = aType; + ServerSemaphore.Signal(); + TaskCompletionSemaphore.Wait(); + } + +void WaitForReceive(TMsgType aType) + { + TheServerControl = EWaitForReceive; + TheMsgType = aType; + ServerSemaphore.Signal(); + TaskCompletionSemaphore.Wait(); + } + +void ReceiveMsg(TMsgType aType) + { + TheServerControl = EReceiveMsg; + TheMsgType = aType; + ServerSemaphore.Signal(); + TaskCompletionSemaphore.Wait(); + } + +void CompleteMsg(TMsgType aType) + { + TheServerControl = ECompleteMsg; + TheMsgType = aType; + ServerSemaphore.Signal(); + TaskCompletionSemaphore.Wait(); + } + +void SetCookie() + { + TheServerControl = ESetCookie; + TheMsgType = EConnect; + ServerSemaphore.Signal(); + TaskCompletionSemaphore.Wait(); + } + +void SetCookie_NoWait() + { + TheServerControl = ESetCookie; + TheMsgType = EConnect; + ServerSemaphore.Signal(); + } + +void SetNullCookie() + { + TheServerControl = ESetNullCookie; + TheMsgType = EConnect; + ServerSemaphore.Signal(); + } + +void SetBadCookie(TMsgType aType) + { + TheServerControl = ESetCookie; + test(aType != EConnect); + TheMsgType = aType; + ServerSemaphore.Signal(); + } +void SetClientCritical(User::TCritical aCritical) + { + TheClientControl = ESetCritical; + CriticalLevel=aCritical; + ClientSemaphore.Signal(); + TaskCompletionSemaphore.Wait(); + } + +void Test1() + { + test.Next(_L("Create session with test server")); + CreateSession(); + test.Next(_L("Send connect message")); + SendMsg(EConnect); + test.Next(_L("Send A.N.Other message")); + SendMsg(EANOther); + test.Next(_L("Sending disconnect message")); + SendMsg(EDisConnect); + test.Next(_L("Receive A.N.Other message")); + ReceiveMsg(EANOther); + test(Msgs[Index()].Session() == NULL); + test.Next(_L("Receive disconnect message")); + ReceiveMsg(EDisConnect); + test.Next(_L("Check the session has gone")); + test(Msgs[Index()].Session() == NULL); + test.Next(_L("Set up receive for next test")); + ReceiveBlocked(EConnect); + } + +void Test2() + { + test.Next(_L("Create session with test server")); + CreateSession(); + test.Next(_L("Send connect message")); + SendMsg(EConnect); + test.Next(_L("Send A.N.Other message")); + SendMsg(EANOther); + test.Next(_L("Receive connect message")); + WaitForReceive(EConnect); + test(Msgs[Index()].Session() == NULL); + test.Next(_L("Receive A.N.Other message")); + ReceiveMsg(EANOther); + test(Msgs[Index()].Session() == NULL); + test.Next(_L("Sending disconnect message")); + SendMsg(EDisConnect); + test.Next(_L("Await disconnect message")); + ReceiveBlocked(EDisConnect); + test.Next(_L("Set cookie")); + SetCookie(); + test.Next(_L("Check disconnect message received")); + WaitForReceive(EDisConnect); + test(Msgs[Index()].Session() == KSessionCookie); + test.Next(_L("Complete connect message")); + CompleteMsg(EConnect); + } + +void Test2a() + { + CreateSession(); + SendMsg(EConnect); + SendMsg(EANOther); + ReceiveMsg(EConnect); + test(Msgs[Index()].Session() == NULL); + ReceiveMsg(EANOther); + test(Msgs[Index()].Session() == NULL); + SendMsg(EDisConnect); + ReceiveBlocked(EDisConnect); + CompleteMsg(EConnect); + WaitForReceive(EDisConnect); + test(Msgs[Index()].Session() == NULL); + } + +void Test2b() + { + CreateSession(); + SendMsg(EConnect); + SendMsg(EANOther); + ReceiveMsg(EConnect); + test(Msgs[Index()].Session() == NULL); + SetCookie(); + ReceiveMsg(EANOther); + test(Msgs[Index()].Session() == KSessionCookie); + SendMsg(EDisConnect); + ReceiveMsg(EDisConnect); + test(Msgs[Index()].Session() == KSessionCookie); + } + +void Test3() + { + CreateSession(); + SendMsg(EConnect); + ReceiveMsg(EConnect); + test(Msgs[Index()].Session() == NULL); + SendMsg(EANOther); + ReceiveMsg(EANOther); + test(Msgs[Index()].Session() == NULL); + SendMsg(EDisConnect); + ReceiveBlocked(EDisConnect); + SetCookie(); + WaitForReceive(EDisConnect); + test(Msgs[Index()].Session() == KSessionCookie); + CompleteMsg(EConnect); + } + +void Test3a() + { + CreateSession(); + SendMsg(EConnect); + ReceiveMsg(EConnect); + test(Msgs[Index()].Session() == NULL); + SendMsg(EANOther); + ReceiveMsg(EANOther); + test(Msgs[Index()].Session() == NULL); + SendMsg(EDisConnect); + ReceiveBlocked(EDisConnect); + CompleteMsg(EConnect); + WaitForReceive(EDisConnect); + test(Msgs[Index()].Session() == NULL); + } + +void Test3b() + { + CreateSession(); + SendMsg(EConnect); + ReceiveMsg(EConnect); + test(Msgs[Index()].Session() == NULL); + SetCookie(); + SendMsg(EANOther); + ReceiveMsg(EANOther); + test(Msgs[Index()].Session() == KSessionCookie); + SendMsg(EDisConnect); + ReceiveMsg(EDisConnect); + test(Msgs[Index()].Session() == KSessionCookie); + } + +void Test4() + { + CreateSession(); + SendMsg(EANOther); + SendMsg(EConnect); + SendMsg(EANOther2); + SendMsg(EDisConnect); + ReceiveMsg(EANOther); + test(Msgs[Index()].Session() == NULL); + ReceiveMsg(EANOther2); + test(Msgs[Index()].Session() == NULL); + ReceiveMsg(EDisConnect); + test(Msgs[Index()].Session() == NULL); + } + +void Test5() + { + CreateSession(); + SendMsg(EANOther); + SendMsg(EConnect); + SendMsg(EANOther2); + ReceiveMsg(EANOther); + test(Msgs[Index()].Session() == NULL); + SendMsg(EDisConnect); + ReceiveMsg(EANOther2); + test(Msgs[Index()].Session() == NULL); + ReceiveMsg(EDisConnect); + test(Msgs[Index()].Session() == NULL); + ReceiveBlocked(EANOther); + } + +void Test6() + { + CreateSession(); + SendMsg(EANOther); + SendMsg(EConnect); + SendMsg(EANOther2); + WaitForReceive(EANOther); + test(Msgs[Index()].Session() == NULL); + ReceiveMsg(EConnect); + test(Msgs[Index()].Session() == NULL); + ReceiveMsg(EANOther2); + test(Msgs[Index()].Session() == NULL); + SendMsg(EDisConnect); + ReceiveBlocked(EDisConnect); + SetCookie(); + WaitForReceive(EDisConnect); + test(Msgs[Index()].Session() == KSessionCookie); + CompleteMsg(EConnect); + } + +void Test6a() + { + CreateSession(); + SendMsg(EANOther); + SendMsg(EConnect); + SendMsg(EANOther2); + ReceiveMsg(EANOther); + test(Msgs[Index()].Session() == NULL); + ReceiveMsg(EConnect); + test(Msgs[Index()].Session() == NULL); + ReceiveMsg(EANOther2); + test(Msgs[Index()].Session() == NULL); + SendMsg(EDisConnect); + ReceiveBlocked(EDisConnect); + CompleteMsg(EConnect); + WaitForReceive(EDisConnect); + test(Msgs[Index()].Session() == NULL); + } + +void Test6b() + { + CreateSession(); + SendMsg(EANOther); + SendMsg(EConnect); + SendMsg(EANOther2); + ReceiveMsg(EANOther); + test(Msgs[Index()].Session() == NULL); + ReceiveMsg(EConnect); + test(Msgs[Index()].Session() == NULL); + SetCookie(); + ReceiveMsg(EANOther2); + test(Msgs[Index()].Session() == KSessionCookie); + SendMsg(EDisConnect); + ReceiveMsg(EDisConnect); + test(Msgs[Index()].Session() == KSessionCookie); + } + +void Test7() + { + CreateSession(); + SendMsg(EANOther); + SendMsg(EConnect); + ReceiveMsg(EANOther); + test(Msgs[Index()].Session() == NULL); + SendMsg(EANOther2); + ReceiveMsg(EConnect); + test(Msgs[Index()].Session() == NULL); + SetCookie(); + ReceiveMsg(EANOther2); + test(Msgs[Index()].Session() == KSessionCookie); + SendMsg(EDisConnect); + ReceiveMsg(EDisConnect); + test(Msgs[Index()].Session() == KSessionCookie); + } + +void Test8() + { + CreateSession(); + SendMsg(EANOther); + SendMsg(EConnect); + ReceiveMsg(EANOther); + test(Msgs[Index()].Session() == NULL); + ReceiveMsg(EConnect); + test(Msgs[Index()].Session() == NULL); + SetCookie(); + SendMsg(EANOther2); + ReceiveMsg(EANOther2); + test(Msgs[Index()].Session() == KSessionCookie); + SendMsg(EDisConnect); + ReceiveMsg(EDisConnect); + test(Msgs[Index()].Session() == KSessionCookie); + } + +void Test9() + { + CreateSession(); + SendMsg(EANOther); + ReceiveMsg(EANOther); + test(Msgs[Index()].Session() == NULL); + SendMsg(EConnect); + ReceiveMsg(EConnect); + test(Msgs[Index()].Session() == NULL); + SetCookie(); + SendMsg(EANOther2); + ReceiveMsg(EANOther2); + test(Msgs[Index()].Session() == KSessionCookie); + SendMsg(EDisConnect); + ReceiveMsg(EDisConnect); + test(Msgs[Index()].Session() == KSessionCookie); + } + +void Test10() + { + // Try connecting with too many message slots + // (Check for DEF091903 regression) + CreateSession(KErrArgument, 1000); + } + +_LIT(KKernExec, "KERN-EXEC"); + +void CheckClientDeath(TInt aReason) + { + TRequestStatus logon; + + ClientThread.Logon(logon); + User::WaitForRequest(logon); + + test(ClientThread.ExitType() == EExitPanic); + test(ClientThread.ExitCategory() == KKernExec); + test(ClientThread.ExitReason() == aReason); + + ClientThread.Close(); + ClientThread.SetHandle(KNullHandle); + } + +void CheckServerDeath(TInt aReason) + { + TRequestStatus logon; + + ServerThread.Logon(logon); + User::WaitForRequest(logon); + + test(ServerThread.ExitType() == EExitPanic); + test(ServerThread.ExitCategory() == KKernExec); + test(ServerThread.ExitReason() == aReason); + + CLOSE_AND_WAIT(ServerThread); + ServerThread.SetHandle(KNullHandle); + } + +void TestNaughty() + { + TBool jit = User::JustInTime(); + User::SetJustInTime(EFalse); + + SetClientCritical(User::ENotCritical); + test.Next(_L("Two connect msgs at once is naughty")); + CreateSession(); + SendMsg(EConnect); + ReceiveMsg(EConnect); + SetCookie(); + SendMsg_NoWait(EConnect); + CheckClientDeath(ERequestAlreadyPending); + StartClient(KClientThread2); + test.Next(_L("Another connect message after a sucessful connect msg is naughty")); + CreateSession(); + SendMsg(EConnect); + ReceiveMsg(EConnect); + SetCookie(); + CompleteMsg(EConnect); + SendMsg_NoWait(EConnect); + CheckClientDeath(ESessionAlreadyConnected); + StartClient(KClientThread3); + + test.Next(_L("A null session cookie is naughty")); + CreateSession(); + SendMsg(EConnect); + ReceiveMsg(EConnect); + SetNullCookie(); + CheckServerDeath(ESessionNullCookie); + StartServer(); + + test.Next(_L("Setting the session cookie twice is naughty")); + CreateSession(); + SendMsg(EConnect); + ReceiveMsg(EConnect); + SetCookie(); + SetCookie_NoWait(); + CheckServerDeath(ESessionCookieAlreadySet); + StartServer(); + + test.Next(_L("Trying to set the session cookie from a non-connect message is naughty")); + CreateSession(); + SendMsg(EConnect); + ReceiveMsg(EConnect); + SendMsg(EANOther); + ReceiveMsg(EANOther); + SetBadCookie(EANOther); + CheckServerDeath(ESessionInvalidCookieMsg); + StartServer(); + + User::SetJustInTime(jit); + } + +TInt E32Main() + { + User::RenameThread(KMainThread); + + __UHEAP_MARK; + + test.Title(); + + test.Start(_L("Creating semaphores")); + CreateSemaphores(); + + test.Next(_L("Starting test server")); + StartServer(); + + test.Next(_L("Starting test client")); + StartClient(); + SetClientCritical(User::EProcessCritical); + // test combinations of receiving messages with messages sent by the client in the + // correct order (w.r.t to each other, but not necessarily to when messages are received) + test.Next(_L("Sending in order")); + test.Next(_L("1")); + Test1(); + test.Next(_L("2")); + Test2(); + test.Next(_L("2a")); + Test2a(); + test.Next(_L("2b")); + Test2b(); + test.Next(_L("3")); + Test3(); + test.Next(_L("3a")); + Test3a(); + test.Next(_L("3b")); + Test3b(); + + // test combinations of receiving messages with messages sent by the client in the + // wrong order (w.r.t to each other, but not necessarily to when messages are received) + test.Next(_L("Sending out of order")); + test.Next(_L("4")); + Test4(); + test.Next(_L("5")); + Test5(); + test.Next(_L("6")); + Test6(); + test.Next(_L("6a")); + Test6a(); + test.Next(_L("6b")); + Test6b(); + test.Next(_L("7")); + Test7(); + test.Next(_L("8")); + Test8(); + test.Next(_L("9")); + Test9(); + test.Next(_L("10")); + Test10(); + + test.Next(_L("Test other naughty behaviour is trapped")); + TestNaughty(); + + test.Next(_L("Stopping test client")); + StopClient(); + + test.Next(_L("Stopping test server")); + StopServer(); + + test.Next(_L("Closing semaphores")); + CloseSemaphores(); + + test.End(); + test.Close(); + + __UHEAP_MARKEND; + + return KErrNone; + }