|
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 } |