genericopenlibs/cstdlib/TSTLIB/TCANCEL.CPP
changeset 31 ce057bb09d0b
parent 0 e4d67989cc36
equal deleted inserted replaced
30:e20de85af2ee 31:ce057bb09d0b
       
     1 // Copyright (c) 1999-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 "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 // Test code for interrupted IO operations
       
    15 // 
       
    16 //
       
    17 
       
    18 #include <e32std.h>
       
    19 #include <e32svr.h>	// for RDebug
       
    20 #include <stdlib.h>
       
    21 #include <unistd.h>
       
    22 #include <stdio.h>
       
    23 #include <string.h>
       
    24 #include <sys/fcntl.h>
       
    25 #include <sys/errno.h>
       
    26 
       
    27 #include <sys/ioctl.h>		// for E32IOSELECT
       
    28 #include <sys/socket.h>
       
    29 #include <libc/netinet/in.h>
       
    30 
       
    31 extern "C" {
       
    32 #include "CTEST.H"
       
    33 }
       
    34 test_Data;
       
    35 
       
    36 #include <estlib.h>	// for multi-threading control
       
    37 
       
    38 int testFid;
       
    39 struct sockaddr_in testAddr;
       
    40 RSemaphore semaphores[2];
       
    41 
       
    42 void init_test()
       
    43 	{
       
    44 	// We need a datagram socket that we can send to
       
    45 
       
    46 	test_Next("Create datagram socket");
       
    47 	testFid=socket(PF_INET, SOCK_DGRAM, 0);
       
    48 	test_ok(testFid>=0);
       
    49 	
       
    50 	test_Next("Bind to local address");
       
    51 	IN_SET_LOOPBACK_ADDR(&testAddr);
       
    52 	testAddr.sin_port=0;
       
    53 
       
    54 	size_t len=sizeof(testAddr);
       
    55 	int err=bind(testFid, (struct sockaddr*)&testAddr, len);
       
    56 	test_ok(err==0);
       
    57 
       
    58 	err=getsockname(testFid, (struct sockaddr*)&testAddr, &len);
       
    59 	test_ok(err==0);
       
    60 
       
    61 	// We now have a datagram socket with a known address
       
    62 
       
    63 	test_Next("Create semaphores for test synchronisation");
       
    64 	for (int i=0; i<2; i++)
       
    65 		{
       
    66 		err=semaphores[i].CreateLocal(0);
       
    67 		test(err==KErrNone);
       
    68 		}
       
    69 	}
       
    70 
       
    71 /**
       
    72 Test of the asynchronous ioctl & cancel code
       
    73 
       
    74 @SYMTestCaseID          SYSLIB-STDLIB-CT-1044
       
    75 @SYMTestCaseDesc	    Tests for the asynchronous ioctl & cancel code
       
    76 @SYMTestPriority 	    High
       
    77 @SYMTestActions  	    Tests that E32IOSELECT ioctl is working
       
    78 						Tests for asynchronous IOCTL.
       
    79 						Setup asynchronous IOCTL which won't complete, then cancel.Check for cancel status
       
    80 						Cancel a completed asynchronous IOCTL,and check for no error
       
    81 @SYMTestExpectedResults Test must not fail
       
    82 @SYMREQ                 REQ0000
       
    83 */		
       
    84 void test_ioctl()
       
    85 	{
       
    86 	// confirm that the E32IOSELECT ioctl is working
       
    87 	test_Next("Check synchronous IOCTL");
       
    88 	int mask=E32SELECT_READ|E32SELECT_WRITE|E32SELECT_EXCEPT;
       
    89 	int err=ioctl(testFid,E32IOSELECT,&mask);
       
    90 	test_ok(err==0);
       
    91 	test(mask==E32SELECT_WRITE);
       
    92 
       
    93 	test_Next("Check asynchronous IOCTL");
       
    94 	TRequestStatus status;
       
    95 	mask=E32SELECT_READ|E32SELECT_WRITE|E32SELECT_EXCEPT;
       
    96 	err=ioctl(testFid,E32IOSELECT,&mask,status);
       
    97 	test_ok(err==0);
       
    98 	User::WaitForRequest(status);
       
    99 	test(status.Int()==KErrNone);
       
   100 	err=ioctl_complete(testFid,E32IOSELECT,&mask,status);
       
   101 	test_ok(err==0);
       
   102 	test(mask==E32SELECT_WRITE);
       
   103 
       
   104 	test_Next("Setup asynchronous IOCTL which won't complete, then cancel");
       
   105 	mask=E32SELECT_READ;
       
   106 	err=ioctl(testFid,E32IOSELECT,&mask,status);
       
   107 	test_ok(err==0);
       
   108 	test(status.Int()==KRequestPending);	// i.e. waiting for input to arrive
       
   109 
       
   110 	// test_Next("Cancel the pending IOCTL");
       
   111 	// Sadly this will do write() which will get a KErrInUse and then panic...
       
   112 	err=ioctl_cancel(testFid);
       
   113 	test_ok(err==0);
       
   114 	User::WaitForRequest(status);
       
   115 	test_Next("Check that ioctl_cancel worked");
       
   116 	test(status.Int()==KErrCancel);			// i.e. it was cancelled
       
   117 
       
   118 	test_Next("Cancel a completed asynchronous IOCTL");
       
   119 	mask=E32SELECT_WRITE;
       
   120 	err=ioctl(testFid,E32IOSELECT,&mask,status);
       
   121 	test_ok(err==0);
       
   122 	
       
   123 	while (status.Int() == KRequestPending)
       
   124 		User::After(5000);
       
   125 
       
   126 	test(status.Int()!=KRequestPending);	// i.e. select has completed
       
   127 
       
   128 	// test_Next("Cancel the pending IOCTL");
       
   129 	// Sadly this will do write() which will get a KErrInUse and then panic...
       
   130 	err=ioctl_cancel(testFid);
       
   131 	test_ok(err==0);
       
   132 	User::WaitForRequest(status);
       
   133 	test(status.Int()==KErrNone);			// i.e. it was cancelled
       
   134 
       
   135 	}
       
   136 
       
   137 // Thread functions which will block accessing the socket
       
   138 
       
   139 TInt ioctl_block(TAny* aSemIndex)
       
   140 	{
       
   141 	semaphores[(TInt)aSemIndex].Wait();		// block until the test is ready
       
   142 
       
   143 	int mask=E32SELECT_READ;
       
   144 	int err=ioctl(testFid,E32IOSELECT,&mask);
       
   145 	test_ok(err==0);
       
   146 	test(mask==E32SELECT_READ);
       
   147 	return 1;
       
   148 	}
       
   149 
       
   150 TInt recv_block(TAny* aSemIndex)
       
   151 	{
       
   152 	semaphores[(TInt)aSemIndex].Wait();		// block until the test is ready
       
   153 
       
   154 	char buf[256];
       
   155 	// Problem in recvfrom: int err=recvfrom(testFid,buf,MSG_PEEK,sizeof(buf),0,0);
       
   156 	struct sockaddr_in junk;
       
   157 	size_t junklen=sizeof(junk);
       
   158 	// Problem in esock/tcpip: int err=recvfrom(testFid,buf,sizeof(buf),MSG_PEEK,(struct sockaddr*)&junk,&junklen);
       
   159 	int err=recvfrom(testFid,buf,sizeof(buf),0,(struct sockaddr*)&junk,&junklen);
       
   160 	// Problem in recfrom: test_ok(err>0);
       
   161 	test_ok(err>=0);
       
   162 	return 1;
       
   163 	}
       
   164 
       
   165 void kill_and_check(RThread& aVictim, TRequestStatus& aVictimStatus, TRequestStatus& aSurvivorStatus)
       
   166 	{
       
   167 	test(aVictimStatus.Int()==KRequestPending);
       
   168 	test(aSurvivorStatus.Int()==KRequestPending);
       
   169 	aVictim.Kill(666);
       
   170 	char* KDatagram="Mine is the last voice you will ever hear";
       
   171 	int length=strlen(KDatagram)+1;
       
   172 	
       
   173 	test_Next("Send datagram");
       
   174 	int err=sendto(testFid,KDatagram, length,0,(struct sockaddr*)&testAddr,sizeof(testAddr));
       
   175 	test_ok(err==length);
       
   176 	User::After(1);
       
   177 
       
   178 	test_Next("Check the victim status");
       
   179 	User::WaitForRequest(aVictimStatus);
       
   180 	test(aVictimStatus.Int()==666);
       
   181 
       
   182 	test_Next("Check the survivor status");
       
   183 	User::WaitForRequest(aSurvivorStatus);
       
   184 	test(aSurvivorStatus.Int()==1);
       
   185 
       
   186 	// Check to see if the datagram has been swallowed
       
   187 	int mask=E32SELECT_READ|E32SELECT_WRITE|E32SELECT_EXCEPT;
       
   188 	err=ioctl(testFid,E32IOSELECT,&mask);
       
   189 	test_ok(err==0);
       
   190 	if ((mask&E32SELECT_READ)==0)
       
   191 		return;		// yes - nothing to read
       
   192 
       
   193 	test_Next("Consume the datagram");
       
   194 	char buf[256];
       
   195 	// Problem in recvfrom: err=recvfrom(testFid,buf,sizeof(buf),0,0,0);
       
   196 	struct sockaddr_in junk;
       
   197 	size_t junklen=sizeof(junk);
       
   198 	err=recvfrom(testFid,buf,sizeof(buf),0,(struct sockaddr*)&junk,&junklen);
       
   199 	// Problem in recfrom: test_ok(err==length);
       
   200 	test_ok(err>=0);
       
   201 	}
       
   202 /**
       
   203 @SYMTestCaseID          SYSLIB-STDLIB-CT-1045
       
   204 @SYMTestCaseDesc	    Tests for killing an ioctl
       
   205 @SYMTestPriority 	    High
       
   206 @SYMTestActions  	    Create two threads which will block on the socket
       
   207 						then kill one of them and send a datagram 
       
   208 						check the exit status of both threads
       
   209 @SYMTestExpectedResults Test must not fail
       
   210 @SYMREQ                 REQ0000
       
   211 */		
       
   212 void test_killing(TInt aThread, TThreadFunction aFunction, char* aTitle)
       
   213 	{
       
   214 	_LIT(KThreadName, "TCancel Test Thread %d");
       
   215 	TBuf<80> threadName;
       
   216 	static TInt threadNumber=0;
       
   217 
       
   218 	test_Next(aTitle);
       
   219 	// test_Next("Create test thread A");
       
   220 	RThread thread1;
       
   221 	TRequestStatus status1;
       
   222 	threadName.Format(KThreadName,++threadNumber);
       
   223 	TInt err=thread1.Create(threadName,aFunction,0x10000,NULL,(TAny*)0);
       
   224 	test(err==KErrNone);
       
   225 	thread1.Logon(status1);
       
   226 	thread1.Resume();
       
   227 
       
   228 	// test_Next("Create test thread B");
       
   229 	RThread thread2;
       
   230 	TRequestStatus status2;
       
   231 	threadName.Format(KThreadName,++threadNumber);
       
   232 	err=thread2.Create(threadName,aFunction,0x10000,NULL,(TAny*)1);
       
   233 	test(err==KErrNone);
       
   234 	thread2.Logon(status2);
       
   235 	thread2.Resume();
       
   236 
       
   237 	test_Next("Start thread A, then thread B...");
       
   238 	semaphores[0].Signal();
       
   239 	User::After(1);
       
   240 	semaphores[1].Signal();
       
   241 	User::After(1);
       
   242 
       
   243 	if (aThread==1)
       
   244 		{
       
   245 		test_Next("Kill thread A");
       
   246 		kill_and_check(thread1, status1, status2);
       
   247 		}
       
   248 	else
       
   249 		{
       
   250 		test_Next("Kill thread B");
       
   251 		kill_and_check(thread2, status2, status1);
       
   252 		}
       
   253 
       
   254 	thread1.Close();
       
   255 	thread2.Close();
       
   256 	}
       
   257 
       
   258 int main()
       
   259 	{
       
   260 	
       
   261 	start_redirection_server();
       
   262 
       
   263 	test_Title("TCANCEL");
       
   264 	init_test();
       
   265 	test_ioctl();		// explicit cancellation
       
   266 	test_killing(1,ioctl_block, "Cancellation of active ioctl");	
       
   267 	test_killing(2,ioctl_block, "Cancellation of queued ioctl");
       
   268 	test_killing(1,recv_block,  "Cancellation of active recvfrom");	
       
   269 	test_killing(2,recv_block,  "Cancellation of queued recvfrom");
       
   270 	test_Close();
       
   271 	return KErrNone;
       
   272 	}