1
2
3
4
5
6
7
8
9
10
11
12
13
14 package org.eclipse.jetty.continuation.test;
15
16 import java.io.IOException;
17 import java.io.InputStream;
18 import java.net.Socket;
19 import java.util.Timer;
20 import java.util.TimerTask;
21
22 import javax.servlet.ServletException;
23 import javax.servlet.http.HttpServlet;
24 import javax.servlet.http.HttpServletRequest;
25 import javax.servlet.http.HttpServletResponse;
26
27 import junit.framework.TestCase;
28
29 import org.eclipse.jetty.continuation.Continuation;
30 import org.eclipse.jetty.continuation.ContinuationListener;
31 import org.eclipse.jetty.continuation.ContinuationSupport;
32
33
34
35 public abstract class ContinuationBase extends TestCase
36 {
37 protected SuspendServlet _servlet=new SuspendServlet();
38 protected int _port;
39
40 protected void doNormal(String type) throws Exception
41 {
42 String response=process(null,null);
43 assertContains(type,response);
44 assertContains("NORMAL",response);
45 assertNotContains("history: onTimeout",response);
46 assertNotContains("history: onComplete",response);
47 }
48
49 protected void doSleep() throws Exception
50 {
51 String response=process("sleep=200",null);
52 assertContains("SLEPT",response);
53 assertNotContains("history: onTimeout",response);
54 assertNotContains("history: onComplete",response);
55 }
56
57 protected void doSuspend() throws Exception
58 {
59 String response=process("suspend=200",null);
60 assertContains("TIMEOUT",response);
61 assertContains("history: onTimeout",response);
62 assertContains("history: onComplete",response);
63 }
64
65 protected void doSuspendWaitResume() throws Exception
66 {
67 String response=process("suspend=200&resume=10",null);
68 assertContains("RESUMED",response);
69 assertNotContains("history: onTimeout",response);
70 assertContains("history: onComplete",response);
71 }
72
73 protected void doSuspendResume() throws Exception
74 {
75 String response=process("suspend=200&resume=0",null);
76 assertContains("RESUMED",response);
77 assertNotContains("history: onTimeout",response);
78 assertContains("history: onComplete",response);
79 }
80
81 protected void doSuspendWaitComplete() throws Exception
82 {
83 String response=process("suspend=200&complete=50",null);
84 assertContains("COMPLETED",response);
85 assertContains("history: initial",response);
86 assertNotContains("history: onTimeout",response);
87 assertContains("history: onComplete",response);
88 assertNotContains("history: !initial",response);
89 }
90
91 protected void doSuspendComplete() throws Exception
92 {
93 String response=process("suspend=200&complete=0",null);
94 assertContains("COMPLETED",response);
95 assertContains("history: initial",response);
96 assertNotContains("history: onTimeout",response);
97 assertContains("history: onComplete",response);
98 assertNotContains("history: !initial",response);
99 }
100
101 protected void doSuspendWaitResumeSuspendWaitResume() throws Exception
102 {
103 String response=process("suspend=1000&resume=10&suspend2=1000&resume2=10",null);
104 assertEquals(2,count(response,"history: suspend"));
105 assertEquals(2,count(response,"history: resume"));
106 assertEquals(0,count(response,"history: onTimeout"));
107 assertEquals(1,count(response,"history: onComplete"));
108 assertContains("RESUMED",response);
109 }
110
111 protected void doSuspendWaitResumeSuspendComplete() throws Exception
112 {
113 String response=process("suspend=1000&resume=10&suspend2=1000&complete2=10",null);
114 assertEquals(2,count(response,"history: suspend"));
115 assertEquals(1,count(response,"history: resume"));
116 assertEquals(0,count(response,"history: onTimeout"));
117 assertEquals(1,count(response,"history: onComplete"));
118 assertContains("COMPLETED",response);
119 }
120
121 protected void doSuspendWaitResumeSuspend() throws Exception
122 {
123 String response=process("suspend=1000&resume=10&suspend2=10",null);
124 assertEquals(2,count(response,"history: suspend"));
125 assertEquals(1,count(response,"history: resume"));
126 assertEquals(1,count(response,"history: onTimeout"));
127 assertEquals(1,count(response,"history: onComplete"));
128 assertContains("TIMEOUT",response);
129 }
130
131 protected void doSuspendTimeoutSuspendResume() throws Exception
132 {
133 String response=process("suspend=10&suspend2=1000&resume2=10",null);
134 assertEquals(2,count(response,"history: suspend"));
135 assertEquals(1,count(response,"history: resume"));
136 assertEquals(1,count(response,"history: onTimeout"));
137 assertEquals(1,count(response,"history: onComplete"));
138 assertContains("RESUMED",response);
139 }
140
141 protected void doSuspendTimeoutSuspendComplete() throws Exception
142 {
143 String response=process("suspend=10&suspend2=1000&complete2=10",null);
144 assertEquals(2,count(response,"history: suspend"));
145 assertEquals(0,count(response,"history: resume"));
146 assertEquals(1,count(response,"history: onTimeout"));
147 assertEquals(1,count(response,"history: onComplete"));
148 assertContains("COMPLETED",response);
149 }
150
151 protected void doSuspendTimeoutSuspend() throws Exception
152 {
153 String response=process("suspend=10&suspend2=10",null);
154 assertEquals(2,count(response,"history: suspend"));
155 assertEquals(0,count(response,"history: resume"));
156 assertEquals(2,count(response,"history: onTimeout"));
157 assertEquals(1,count(response,"history: onComplete"));
158 assertContains("TIMEOUT",response);
159 }
160
161 protected void doSuspendThrowResume() throws Exception
162 {
163 String response=process("suspend=200&resume=10&undispatch=true",null);
164 assertContains("RESUMED",response);
165 assertNotContains("history: onTimeout",response);
166 assertContains("history: onComplete",response);
167 }
168
169 protected void doSuspendResumeThrow() throws Exception
170 {
171 String response=process("suspend=200&resume=0&undispatch=true",null);
172 assertContains("RESUMED",response);
173 assertNotContains("history: onTimeout",response);
174 assertContains("history: onComplete",response);
175 }
176
177 protected void doSuspendThrowComplete() throws Exception
178 {
179 String response=process("suspend=200&complete=10&undispatch=true",null);
180 assertContains("COMPLETED",response);
181 assertNotContains("history: onTimeout",response);
182 assertContains("history: onComplete",response);
183 }
184
185 protected void doSuspendCompleteThrow() throws Exception
186 {
187 String response=process("suspend=200&complete=0&undispatch=true",null);
188 assertContains("COMPLETED",response);
189 assertNotContains("history: onTimeout",response);
190 assertContains("history: onComplete",response);
191 }
192
193
194 private int count(String responses,String substring)
195 {
196 int count=0;
197 int i=responses.indexOf(substring);
198 while (i>=0)
199 {
200 count++;
201 i=responses.indexOf(substring,i+substring.length());
202 }
203
204 return count;
205 }
206
207 protected void assertContains(String content,String response)
208 {
209 assertEquals("HTTP/1.1 200 OK",response.substring(0,15));
210 if (response.indexOf(content,15)<0)
211 {
212 System.err.println("'"+content+"' NOT IN:\n"+response+"\n--");
213 assertTrue(false);
214 }
215 }
216
217 protected void assertNotContains(String content,String response)
218 {
219 assertEquals("HTTP/1.1 200 OK",response.substring(0,15));
220 if (response.indexOf(content,15)>=0)
221 {
222 System.err.println("'"+content+"' IS IN:\n"+response+"'\n--");
223 assertTrue(false);
224 }
225 }
226
227 public synchronized String process(String query,String content) throws Exception
228 {
229 String request = "GET /";
230
231 if (query!=null)
232 request+="?"+query;
233 request+=" HTTP/1.1\r\n"+
234 "Host: localhost\r\n"+
235 "Connection: close\r\n";
236 if (content!=null)
237 request+="Content-Length: "+content.length()+"\r\n";
238 request+="\r\n" + content;
239
240 int port=_port;
241 String response=null;
242 try
243 {
244 Socket socket = new Socket("localhost",port);
245 socket.getOutputStream().write(request.getBytes("UTF-8"));
246
247 response = toString(socket.getInputStream());
248 }
249 catch(Exception e)
250 {
251 System.err.println("failed on port "+port);
252 e.printStackTrace();
253 throw e;
254 }
255 return response;
256 }
257
258
259 protected abstract String toString(InputStream in) throws IOException;
260
261
262 private static class SuspendServlet extends HttpServlet
263 {
264 private Timer _timer=new Timer();
265
266 public SuspendServlet()
267 {}
268
269
270 protected void doGet(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException
271 {
272 final Continuation continuation = ContinuationSupport.getContinuation(request);
273
274 response.addHeader("history",continuation.getClass().toString());
275
276 int read_before=0;
277 long sleep_for=-1;
278 long suspend_for=-1;
279 long suspend2_for=-1;
280 long resume_after=-1;
281 long resume2_after=-1;
282 long complete_after=-1;
283 long complete2_after=-1;
284 boolean undispatch=false;
285
286 if (request.getParameter("read")!=null)
287 read_before=Integer.parseInt(request.getParameter("read"));
288 if (request.getParameter("sleep")!=null)
289 sleep_for=Integer.parseInt(request.getParameter("sleep"));
290 if (request.getParameter("suspend")!=null)
291 suspend_for=Integer.parseInt(request.getParameter("suspend"));
292 if (request.getParameter("suspend2")!=null)
293 suspend2_for=Integer.parseInt(request.getParameter("suspend2"));
294 if (request.getParameter("resume")!=null)
295 resume_after=Integer.parseInt(request.getParameter("resume"));
296 if (request.getParameter("resume2")!=null)
297 resume2_after=Integer.parseInt(request.getParameter("resume2"));
298 if (request.getParameter("complete")!=null)
299 complete_after=Integer.parseInt(request.getParameter("complete"));
300 if (request.getParameter("complete2")!=null)
301 complete2_after=Integer.parseInt(request.getParameter("complete2"));
302 if (request.getParameter("undispatch")!=null)
303 undispatch=Boolean.parseBoolean(request.getParameter("undispatch"));
304
305 if (continuation.isInitial())
306 {
307 ((HttpServletResponse)response).addHeader("history","initial");
308 if (read_before>0)
309 {
310 byte[] buf=new byte[read_before];
311 request.getInputStream().read(buf);
312 }
313 else if (read_before<0)
314 {
315 InputStream in = request.getInputStream();
316 int b=in.read();
317 while(b!=-1)
318 b=in.read();
319 }
320
321 if (suspend_for>=0)
322 {
323 if (suspend_for>0)
324 continuation.setTimeout(suspend_for);
325 continuation.addContinuationListener(__listener);
326 ((HttpServletResponse)response).addHeader("history","suspend");
327 continuation.suspend(response);
328
329 if (complete_after>0)
330 {
331 TimerTask complete = new TimerTask()
332 {
333 @Override
334 public void run()
335 {
336 try
337 {
338 response.setStatus(200);
339 response.getOutputStream().println("COMPLETED\n");
340 continuation.complete();
341 }
342 catch(Exception e)
343 {
344 e.printStackTrace();
345 }
346 }
347 };
348 synchronized (_timer)
349 {
350 _timer.schedule(complete,complete_after);
351 }
352 }
353 else if (complete_after==0)
354 {
355 response.setStatus(200);
356 response.getOutputStream().println("COMPLETED\n");
357 continuation.complete();
358 }
359 else if (resume_after>0)
360 {
361 TimerTask resume = new TimerTask()
362 {
363 @Override
364 public void run()
365 {
366 ((HttpServletResponse)continuation.getServletResponse()).addHeader("history","resume");
367 continuation.resume();
368 }
369 };
370 synchronized (_timer)
371 {
372 _timer.schedule(resume,resume_after);
373 }
374 }
375 else if (resume_after==0)
376 {
377 ((HttpServletResponse)continuation.getServletResponse()).addHeader("history","resume");
378 continuation.resume();
379 }
380
381 if (undispatch)
382 continuation.undispatch();
383 }
384 else if (sleep_for>=0)
385 {
386 try
387 {
388 Thread.sleep(sleep_for);
389 }
390 catch (InterruptedException e)
391 {
392 e.printStackTrace();
393 }
394 response.setStatus(200);
395 response.getOutputStream().println("SLEPT\n");
396 }
397 else
398 {
399 response.setStatus(200);
400 response.getOutputStream().println("NORMAL\n");
401 }
402 }
403 else
404 {
405 ((HttpServletResponse)response).addHeader("history","!initial");
406 if (suspend2_for>=0 && request.getAttribute("2nd")==null)
407 {
408 request.setAttribute("2nd","cycle");
409
410 if (suspend2_for>0)
411 continuation.setTimeout(suspend2_for);
412
413 ((HttpServletResponse)response).addHeader("history","suspend");
414 continuation.suspend(response);
415
416 if (complete2_after>0)
417 {
418 TimerTask complete = new TimerTask()
419 {
420 @Override
421 public void run()
422 {
423 try
424 {
425 response.setStatus(200);
426 response.getOutputStream().println("COMPLETED\n");
427 continuation.complete();
428 }
429 catch(Exception e)
430 {
431 e.printStackTrace();
432 }
433 }
434 };
435 synchronized (_timer)
436 {
437 _timer.schedule(complete,complete2_after);
438 }
439 }
440 else if (complete2_after==0)
441 {
442 response.setStatus(200);
443 response.getOutputStream().println("COMPLETED\n");
444 continuation.complete();
445 }
446 else if (resume2_after>0)
447 {
448 TimerTask resume = new TimerTask()
449 {
450 @Override
451 public void run()
452 {
453 ((HttpServletResponse)response).addHeader("history","resume");
454 continuation.resume();
455 }
456 };
457 synchronized (_timer)
458 {
459 _timer.schedule(resume,resume2_after);
460 }
461 }
462 else if (resume2_after==0)
463 {
464 ((HttpServletResponse)response).addHeader("history","resume");
465 continuation.resume();
466 }
467 if (undispatch)
468 continuation.undispatch();
469 return;
470 }
471 else if (continuation.isExpired())
472 {
473 response.setStatus(200);
474 response.getOutputStream().println("TIMEOUT\n");
475 }
476 else if (continuation.isResumed())
477 {
478 response.setStatus(200);
479 response.getOutputStream().println("RESUMED\n");
480 }
481 else
482 {
483 response.setStatus(200);
484 response.getOutputStream().println("unknown???\n");
485 }
486 }
487 }
488 }
489
490
491 private static ContinuationListener __listener = new ContinuationListener()
492 {
493 public void onComplete(Continuation continuation)
494 {
495 ((HttpServletResponse)continuation.getServletResponse()).addHeader("history","onComplete");
496 }
497
498 public void onTimeout(Continuation continuation)
499 {
500 ((HttpServletResponse)continuation.getServletResponse()).addHeader("history","onTimeout");
501 continuation.resume();
502 }
503
504 };
505 }