1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package net.grinder.plugin.http;
23
24 import static net.grinder.testutility.AssertUtilities.assertArraysEqual;
25 import static net.grinder.testutility.AssertUtilities.assertContains;
26 import static org.junit.Assert.assertEquals;
27 import static org.junit.Assert.assertFalse;
28 import static org.junit.Assert.assertNotNull;
29 import static org.junit.Assert.assertNull;
30 import static org.junit.Assert.assertSame;
31 import static org.junit.Assert.assertTrue;
32 import static org.junit.Assert.fail;
33 import static org.mockito.Matchers.isA;
34 import static org.mockito.Mockito.atLeastOnce;
35 import static org.mockito.Mockito.doThrow;
36 import static org.mockito.Mockito.mock;
37 import static org.mockito.Mockito.reset;
38 import static org.mockito.Mockito.times;
39 import static org.mockito.Mockito.verify;
40 import static org.mockito.Mockito.verifyNoMoreInteractions;
41 import static org.mockito.Mockito.when;
42
43 import java.io.ByteArrayInputStream;
44 import java.io.File;
45 import java.io.FileOutputStream;
46 import java.io.OutputStream;
47 import java.util.Random;
48
49 import net.grinder.common.GrinderException;
50 import net.grinder.common.SSLContextFactory;
51 import net.grinder.engine.process.dcr.DCRContextImplementation;
52 import net.grinder.plugininterface.GrinderPlugin;
53 import net.grinder.plugininterface.PluginException;
54 import net.grinder.plugininterface.PluginProcessContext;
55 import net.grinder.plugininterface.PluginRegistry;
56 import net.grinder.plugininterface.PluginThreadContext;
57 import net.grinder.script.Grinder.ScriptContext;
58 import net.grinder.script.InvalidContextException;
59 import net.grinder.script.Statistics;
60 import net.grinder.script.Statistics.StatisticsForTest;
61 import net.grinder.scriptengine.Instrumenter;
62 import net.grinder.scriptengine.Recorder;
63 import net.grinder.scriptengine.java.JavaScriptEngineService;
64 import net.grinder.statistics.StatisticsIndexMap;
65 import net.grinder.statistics.StatisticsServicesImplementation;
66 import net.grinder.util.InsecureSSLContextFactory;
67 import net.grinder.util.StandardTimeAuthority;
68 import net.grinder.util.TimeAuthority;
69
70 import org.junit.After;
71 import org.junit.Before;
72 import org.junit.Test;
73 import org.mockito.ArgumentCaptor;
74 import org.mockito.Captor;
75 import org.mockito.Mock;
76 import org.mockito.MockitoAnnotations;
77 import org.slf4j.Logger;
78
79 import HTTPClient.HTTPResponse;
80 import HTTPClient.HttpURLConnection;
81 import HTTPClient.NVPair;
82 import HTTPClient.ParseException;
83
84
85
86
87
88
89
90 public class TestHTTPRequest {
91 private static final Random s_random = new Random();
92
93 private final SSLContextFactory m_sslContextFactory =
94 new InsecureSSLContextFactory();
95
96 @Mock private ScriptContext m_scriptContext;
97 @Mock private Statistics m_statistics;
98 @Mock private PluginThreadContext m_threadContext;
99 @Mock private PluginProcessContext m_pluginProcessContext;
100 @Mock private StatisticsForTest m_statisticsForTest;
101
102 @Mock private Logger m_logger;
103 @Captor private ArgumentCaptor<String> m_stringCaptor;
104
105 private HTTPRequestHandler m_handler;
106
107 @Before public void setUp() throws Exception {
108
109 MockitoAnnotations.initMocks(this);
110
111 final HTTPPluginThreadState threadState =
112 new HTTPPluginThreadState(m_threadContext,
113 m_sslContextFactory,
114 null,
115 new StandardTimeAuthority());
116
117 when(m_statistics.isTestInProgress()).thenReturn(false);
118
119 when(m_scriptContext.getStatistics()).thenReturn(m_statistics);
120 when(m_scriptContext.getLogger()).thenReturn(m_logger);
121
122 when(m_pluginProcessContext.getPluginThreadListener())
123 .thenReturn(threadState);
124 when(m_pluginProcessContext.getScriptContext()).thenReturn(m_scriptContext);
125 when(m_pluginProcessContext.getStatisticsServices())
126 .thenReturn(StatisticsServicesImplementation.getInstance());
127
128 new PluginRegistry() {
129 {
130 setInstance(this);
131 }
132
133 @Override
134 public void register(final GrinderPlugin plugin) throws GrinderException {
135 plugin.initialize(m_pluginProcessContext);
136 }
137 };
138
139 HTTPPlugin.getPlugin().initialize(m_pluginProcessContext);
140
141
142 reset(m_statistics);
143
144 m_handler = new HTTPRequestHandler();
145 m_handler.start();
146 }
147
148 @After public void tearDown() throws Exception {
149 m_handler.shutdown();
150 }
151
152 @Test public void testTimeout() throws Exception {
153 final HTTPPluginConnectionDefaults connectionDefaults =
154 HTTPPluginConnectionDefaults.getConnectionDefaults();
155
156 final int originalTimeout = connectionDefaults.getTimeout();
157 final String originalProxyHost = connectionDefaults.getProxyHost();
158 final int originalProxyPort = connectionDefaults.getProxyPort();
159
160 try {
161 connectionDefaults.setTimeout(1);
162
163 try {
164 final HTTPRequest request = new HTTPRequest();
165 request.GET("http://idontexist.grinder.sf.net");
166 fail("Expected TimeoutException");
167 }
168 catch (final TimeoutException e) {
169 }
170
171 try {
172 connectionDefaults.setProxyServer("idontexist.grinder.sf.net", 8080);
173 final HTTPRequest request2 = new HTTPRequest();
174 request2.GET("http://idontexist.grinder.sf.net");
175 fail("Expected TimeoutException");
176 }
177 catch (final TimeoutException e) {
178 }
179 }
180 finally {
181 connectionDefaults.setTimeout(originalTimeout);
182 connectionDefaults.setProxyServer(originalProxyHost, originalProxyPort);
183 }
184 }
185
186 @Test public void testSetUrl() throws Exception {
187 final HTTPRequest httpRequest = new HTTPRequest();
188
189 assertNull(httpRequest.getUrl());
190
191 try {
192 httpRequest.setUrl("foo/bah");
193 fail("Expected URLException");
194 }
195 catch (final URLException e) {
196 }
197
198 assertNull(httpRequest.getUrl());
199
200 try {
201 httpRequest.setUrl("http://foo:bah/blah");
202 fail("Expected ParseException");
203 }
204 catch (final ParseException e) {
205 }
206
207 assertNull(httpRequest.getUrl());
208
209 httpRequest.setUrl("http://foo/bah");
210
211 assertEquals("http://foo/bah", httpRequest.getUrl());
212 }
213
214 @Test public void testSetHeaders() {
215 final HTTPRequest httpRequest = new HTTPRequest();
216
217 assertEquals(0, httpRequest.getHeaders().length);
218
219 final NVPair[] newHeaders = new NVPair[] {
220 new NVPair("name", "value"),
221 new NVPair("another name", "another value"),
222 };
223
224 httpRequest.setHeaders(newHeaders);
225 assertArraysEqual(newHeaders, httpRequest.getHeaders());
226 }
227
228 @Test public void testDELETE() throws Exception {
229 final HTTPRequest request = new HTTPRequest();
230
231 try {
232 request.DELETE();
233 fail("Expected URLException");
234 }
235 catch (final URLException e) {
236 }
237
238 try {
239 request.DELETE("/partial");
240 fail("Expected URLException");
241 }
242 catch (final URLException e) {
243 }
244
245 final HTTPResponse response = request.DELETE(m_handler.getURL());
246 assertEquals(200, response.getStatusCode());
247 assertEquals("DELETE / HTTP/1.1", m_handler.getRequestFirstHeader());
248
249 request.setUrl(m_handler.getURL());
250 final HTTPResponse response2 = request.DELETE("/foo");
251 assertEquals(200, response2.getStatusCode());
252 assertEquals("DELETE /foo HTTP/1.1", m_handler.getRequestFirstHeader());
253
254 final HTTPResponse response3 = request.DELETE();
255 assertEquals(200, response3.getStatusCode());
256 assertEquals("DELETE / HTTP/1.1", m_handler.getRequestFirstHeader());
257
258 final NVPair[] headers = {
259 new NVPair("x", "212"),
260 new NVPair("y", "321"),
261 };
262
263 final HTTPResponse response4 = request.DELETE("/", headers);
264 assertEquals(200, response4.getStatusCode());
265 assertEquals("DELETE / HTTP/1.1", m_handler.getRequestFirstHeader());
266 m_handler.assertRequestContainsHeader("x: 212");
267 m_handler.assertRequestContainsHeader("y: 321");
268
269 final NVPair[] headers2 = {
270 new NVPair("x", "1"),
271 new NVPair("y", "2"),
272 new NVPair("z", "3"),
273 };
274
275 request.setHeaders(headers2);
276
277 request.DELETE("/", headers);
278 m_handler.assertRequestContainsHeader("x: 212");
279 m_handler.assertRequestContainsHeader("y: 321");
280 m_handler.assertRequestContainsHeader("z: 3");
281 m_handler.assertRequestDoesNotContainHeader("y: 2");
282 }
283
284 @Test public void testGET() throws Exception {
285 final HTTPRequest request = new HTTPRequest();
286
287 try {
288 request.GET();
289 fail("Expected URLException");
290 }
291 catch (final URLException e) {
292 }
293
294 try {
295 request.GET("#partial");
296 fail("Expected URLException");
297 }
298 catch (final URLException e) {
299 }
300
301 final HTTPResponse response = request.GET(m_handler.getURL());
302 assertEquals(200, response.getStatusCode());
303 assertEquals("GET / HTTP/1.1", m_handler.getRequestFirstHeader());
304
305 request.setUrl(m_handler.getURL());
306 final HTTPResponse response2 = request.GET("/foo");
307 assertEquals(200, response2.getStatusCode());
308 assertEquals("GET /foo HTTP/1.1", m_handler.getRequestFirstHeader());
309
310 final HTTPResponse response3 = request.GET();
311 assertEquals(200, response3.getStatusCode());
312 assertEquals("GET / HTTP/1.1", m_handler.getRequestFirstHeader());
313
314 final NVPair[] parameters4 = {
315 new NVPair("some", "header"),
316 new NVPair("y", "321"),
317 };
318
319 final HTTPResponse response4 = request.GET("/lah/de/dah", parameters4);
320 assertEquals(200, response4.getStatusCode());
321 assertEquals("GET /lah/de/dah?some=header&y=321 HTTP/1.1",
322 m_handler.getRequestFirstHeader());
323
324 final NVPair[] parameters5 = {
325 new NVPair("another", "header"),
326 new NVPair("y", "331"),
327 };
328
329 request.setUrl(m_handler.getURL() + "/lah/");
330 final HTTPResponse response5 = request.GET(parameters5);
331 assertEquals(200, response5.getStatusCode());
332 assertEquals("GET /lah/?another=header&y=331 HTTP/1.1",
333 m_handler.getRequestFirstHeader());
334
335 final NVPair[] headers = {
336 new NVPair("key", "value"),
337 };
338
339 request.setHeaders(headers);
340 final HTTPResponse response6 = request.GET();
341 assertEquals(200, response6.getStatusCode());
342 assertEquals("GET /lah/ HTTP/1.1", m_handler.getRequestFirstHeader());
343 m_handler.assertRequestContainsHeader("key: value");
344
345 final NVPair[] headers2 = {
346 new NVPair("key", "anotherValue"),
347 new NVPair("x", "1"),
348 new NVPair("y", "2"),
349 };
350
351 request.GET("/", null, headers2);
352 m_handler.assertRequestContainsHeader("x: 1");
353 m_handler.assertRequestContainsHeader("y: 2");
354 m_handler.assertRequestContainsHeader("key: anotherValue");
355 m_handler.assertRequestDoesNotContainHeader("key: value");
356
357 final HTTPResponse response7 = request.GET("//multipleSlashes");
358 assertEquals(200, response7.getStatusCode());
359 assertEquals("GET //multipleSlashes HTTP/1.1",
360 m_handler.getRequestFirstHeader());
361
362 request.GET("/#a fragment", null, new NVPair[] {});
363 assertEquals("GET / HTTP/1.1", m_handler.getRequestFirstHeader());
364 m_handler.assertRequestDoesNotContainHeader("key: anotherValue");
365 m_handler.assertRequestContainsHeader("key: value");
366 }
367
368 @Test public void testHEAD() throws Exception {
369 final HTTPRequest request = new HTTPRequest();
370
371 try {
372 request.HEAD();
373 fail("Expected URLException");
374 }
375 catch (final URLException e) {
376 }
377
378 try {
379 request.HEAD("?partial");
380 fail("Expected URLException");
381 }
382 catch (final URLException e) {
383 }
384
385 final HTTPResponse response = request.HEAD(m_handler.getURL());
386 assertEquals(200, response.getStatusCode());
387 assertEquals("HEAD / HTTP/1.1", m_handler.getRequestFirstHeader());
388
389 request.setUrl(m_handler.getURL());
390 final HTTPResponse response2 = request.HEAD("/foo");
391 assertEquals(200, response2.getStatusCode());
392 assertEquals("HEAD /foo HTTP/1.1", m_handler.getRequestFirstHeader());
393
394 final HTTPResponse response3 = request.HEAD();
395 assertEquals(200, response3.getStatusCode());
396 assertEquals("HEAD / HTTP/1.1", m_handler.getRequestFirstHeader());
397
398 final NVPair[] parameters4 = {
399 new NVPair("some", "header"),
400 new NVPair("y", "321"),
401 };
402
403 final HTTPResponse response4 = request.HEAD("/lah/de/dah", parameters4);
404 assertEquals(200, response4.getStatusCode());
405 assertEquals("HEAD /lah/de/dah?some=header&y=321 HTTP/1.1",
406 m_handler.getRequestFirstHeader());
407
408 final NVPair[] parameters5 = {
409 new NVPair("another", "header"),
410 new NVPair("y", "331"),
411 };
412
413 request.setUrl(m_handler.getURL() + "/lah/");
414 final HTTPResponse response5 = request.HEAD(parameters5);
415 assertEquals(200, response5.getStatusCode());
416 assertEquals("HEAD /lah/?another=header&y=331 HTTP/1.1",
417 m_handler.getRequestFirstHeader());
418
419 final NVPair[] headers6 = {
420 new NVPair("key", "value"),
421 };
422
423 request.setHeaders(headers6);
424 final HTTPResponse response6 = request.HEAD();
425 assertEquals(200, response6.getStatusCode());
426 assertEquals("HEAD /lah/ HTTP/1.1", m_handler.getRequestFirstHeader());
427 m_handler.assertRequestContainsHeader("key: value");
428 }
429
430 @Test public void testOPTIONS() throws Exception {
431 final HTTPRequest request = new HTTPRequest();
432
433 try {
434 request.OPTIONS();
435 fail("Expected URLException");
436 }
437 catch (final URLException e) {
438 }
439
440 try {
441 request.OPTIONS("///::partial");
442 fail("Expected URLException");
443 }
444 catch (final URLException e) {
445 }
446
447 final HTTPResponse response = request.OPTIONS(m_handler.getURL());
448 assertEquals(200, response.getStatusCode());
449 assertEquals("OPTIONS / HTTP/1.1", m_handler.getRequestFirstHeader());
450
451 request.setUrl(m_handler.getURL());
452 final HTTPResponse response2 = request.OPTIONS("/foo");
453 assertEquals(200, response2.getStatusCode());
454 assertEquals("OPTIONS /foo HTTP/1.1", m_handler.getRequestFirstHeader());
455
456 final HTTPResponse response3 = request.OPTIONS();
457 assertEquals(200, response3.getStatusCode());
458 assertEquals("OPTIONS / HTTP/1.1", m_handler.getRequestFirstHeader());
459
460 final byte[] data4 = randomBytes(10);
461
462 final HTTPResponse response4 = request.OPTIONS("/blah", data4);
463 assertEquals(200, response4.getStatusCode());
464 assertEquals("OPTIONS /blah HTTP/1.1", m_handler.getRequestFirstHeader());
465 assertArraysEqual(data4, m_handler.getLastRequestBody());
466
467 final byte[] data5 = randomBytes(100);
468
469 request.setUrl(m_handler.getURL() + "/lah/");
470 request.setData(data5);
471 final HTTPResponse response5 = request.OPTIONS("/blah");
472 assertEquals(200, response5.getStatusCode());
473 assertEquals("OPTIONS /blah HTTP/1.1", m_handler.getRequestFirstHeader());
474 assertArraysEqual(data5, m_handler.getLastRequestBody());
475
476 final NVPair[] headers6 = {
477 new NVPair("key", "value"),
478 };
479
480 request.setHeaders(headers6);
481 final HTTPResponse response6 = request.OPTIONS();
482 assertEquals(200, response6.getStatusCode());
483 assertEquals("OPTIONS /lah/ HTTP/1.1", m_handler.getRequestFirstHeader());
484 m_handler.assertRequestContainsHeader("key: value");
485
486 final byte[] data6 = randomBytes(10000);
487
488 final HTTPResponse response7 =
489 request.OPTIONS("/blah", new ByteArrayInputStream(data6));
490 assertEquals(200, response7.getStatusCode());
491 assertEquals("OPTIONS /blah HTTP/1.1", m_handler.getRequestFirstHeader());
492 assertArraysEqual(data6, m_handler.getLastRequestBody());
493
494 final byte[] data7 = randomBytes(10000);
495
496 final HTTPResponse response8 =
497 request.OPTIONS("/blah", new ByteArrayInputStream(data7), headers6);
498 assertEquals(200, response8.getStatusCode());
499 assertEquals("OPTIONS /blah HTTP/1.1", m_handler.getRequestFirstHeader());
500 assertArraysEqual(data7, m_handler.getLastRequestBody());
501 m_handler.assertRequestContainsHeader("key: value");
502 }
503
504 @Test public void testPOST() throws Exception {
505 final HTTPRequest request = new HTTPRequest();
506
507 try {
508 request.POST();
509 fail("Expected URLException");
510 }
511 catch (final URLException e) {
512 }
513
514 try {
515 request.POST("#:/partial");
516 fail("Expected URLException");
517 }
518 catch (final URLException e) {
519 }
520
521 final HTTPResponse response = request.POST(m_handler.getURL());
522 assertEquals(200, response.getStatusCode());
523 assertEquals("POST / HTTP/1.1", m_handler.getRequestFirstHeader());
524
525 request.setUrl(m_handler.getURL());
526 final HTTPResponse response2 = request.POST("/foo");
527 assertEquals(200, response2.getStatusCode());
528 assertEquals("POST /foo HTTP/1.1", m_handler.getRequestFirstHeader());
529
530 final HTTPResponse response3 = request.POST();
531 assertEquals(200, response3.getStatusCode());
532 assertEquals("POST / HTTP/1.1", m_handler.getRequestFirstHeader());
533
534 final byte[] data4 = randomBytes(10);
535
536 final HTTPResponse response4 = request.POST("/blah", data4);
537 assertEquals(200, response4.getStatusCode());
538 assertEquals("POST /blah HTTP/1.1", m_handler.getRequestFirstHeader());
539 assertArraysEqual(data4, m_handler.getLastRequestBody());
540
541 final byte[] data5 = randomBytes(100);
542
543 request.setUrl(m_handler.getURL() + "/lah/");
544 request.setData(data5);
545 final HTTPResponse response5 = request.POST("/blah");
546 assertEquals(200, response5.getStatusCode());
547 assertEquals("POST /blah HTTP/1.1", m_handler.getRequestFirstHeader());
548 assertArraysEqual(data5, m_handler.getLastRequestBody());
549
550 final NVPair[] headers6 = {
551 new NVPair("key", "value"),
552 };
553
554 request.setHeaders(headers6);
555 final HTTPResponse response6 = request.POST();
556 assertEquals(200, response6.getStatusCode());
557 assertEquals("POST /lah/ HTTP/1.1", m_handler.getRequestFirstHeader());
558 m_handler.assertRequestContainsHeader("key: value");
559
560 final NVPair[] formData7 = {
561 new NVPair("Vessel", "Grace of Lefkas"),
562 };
563
564 final HTTPResponse response7 = request.POST("/foo?abc=def", formData7);
565 assertEquals(200, response7.getStatusCode());
566 assertEquals("POST /foo?abc=def HTTP/1.1",
567 m_handler.getRequestFirstHeader());
568 m_handler.assertRequestContainsHeader("key: value");
569 final String bodyText7 = new String(m_handler.getLastRequestBody());
570 assertTrue(bodyText7.indexOf("Vessel=Grace+of+Lefkas") > -1);
571
572 final NVPair[] formData8 = {
573 new NVPair("LOA", "12.3m"),
574 new NVPair("Draught", "1.7"),
575 };
576
577 request.setFormData(formData8);
578
579 final HTTPResponse response8 = request.POST();
580 assertEquals(200, response8.getStatusCode());
581 assertEquals("POST /lah/ HTTP/1.1", m_handler.getRequestFirstHeader());
582 m_handler.assertRequestContainsHeader("key: value");
583 assertArraysEqual(data5, m_handler.getLastRequestBody());
584
585 request.setData(null);
586
587 final HTTPResponse response9 = request.POST();
588 assertEquals(200, response9.getStatusCode());
589 assertEquals("POST /lah/ HTTP/1.1", m_handler.getRequestFirstHeader());
590 m_handler.assertRequestContainsHeader("key: value");
591 final String bodyText9 = new String(m_handler.getLastRequestBody());
592 assertTrue(bodyText9.indexOf("LOA=12.3m") > -1);
593
594 final HTTPResponse response10 = request.POST(formData7);
595 assertEquals(200, response10.getStatusCode());
596 assertEquals("POST /lah/ HTTP/1.1", m_handler.getRequestFirstHeader());
597 final String bodyText10 = new String(m_handler.getLastRequestBody());
598 assertTrue(bodyText10.indexOf("Vessel=Grace+of+Lefkas") > -1);
599
600 final byte[] data6 = randomBytes(10000);
601
602 final HTTPResponse response11 = request.POST("/bhxhh",
603 new ByteArrayInputStream(data6));
604 assertEquals(200, response11.getStatusCode());
605 assertEquals("POST /bhxhh HTTP/1.1", m_handler.getRequestFirstHeader());
606 assertArraysEqual(data6, m_handler.getLastRequestBody());
607
608 final byte[] data7 = randomBytes(10000);
609
610 final HTTPResponse response12 =
611 request.POST("/bhxhh", new ByteArrayInputStream(data7), headers6);
612 assertEquals(200, response12.getStatusCode());
613 assertEquals("POST /bhxhh HTTP/1.1", m_handler.getRequestFirstHeader());
614 assertArraysEqual(data7, m_handler.getLastRequestBody());
615 m_handler.assertRequestContainsHeader("key: value");
616
617 headers6[0] = new NVPair("Content-Length", Integer.toString(data7.length));
618
619 final HTTPResponse response13 =
620 request.POST("/bhxhh", new ByteArrayInputStream(data7), headers6);
621 assertEquals(200, response13.getStatusCode());
622 assertEquals("POST /bhxhh HTTP/1.1", m_handler.getRequestFirstHeader());
623 assertArraysEqual(data7, m_handler.getLastRequestBody());
624 m_handler.assertRequestContainsHeader("Content-length: " + data7.length);
625 }
626
627 @Test public void testPOSTMultiPart() throws Exception {
628 final HTTPRequest request = new HTTPRequest();
629 request.setUrl(m_handler.getURL());
630
631 final NVPair[] formData = {
632 new NVPair("Vessel", "Grace of Lefkas"),
633 };
634
635 request.setHeaders(new NVPair[] { new NVPair("key", "value"), });
636
637 final NVPair[] headers2 = {
638 new NVPair("Content-Type", "multipart/form-data; boundary=---------------------------7db2b32b130706"),
639 };
640
641 final HTTPResponse response =
642 request.POST("/foo?abc=def", formData, headers2, true);
643 assertEquals(200, response.getStatusCode());
644 assertEquals("POST /foo?abc=def HTTP/1.1",
645 m_handler.getRequestFirstHeader());
646
647 m_handler.assertRequestContainsHeader("key: value");
648
649 final String bodyText = new String(m_handler.getLastRequestBody());
650 assertTrue(bodyText.indexOf("Grace of Lefkas") > -1);
651 }
652
653 @Test public void testPUT() throws Exception {
654 final HTTPRequest request = new HTTPRequest();
655
656 try {
657 request.PUT();
658 fail("Expected URLException");
659 }
660 catch (final URLException e) {
661 }
662
663 try {
664 request.PUT("?:/partial");
665 fail("Expected URLException");
666 }
667 catch (final URLException e) {
668 }
669
670 final HTTPResponse response = request.PUT(m_handler.getURL());
671 assertEquals(200, response.getStatusCode());
672 assertEquals("PUT / HTTP/1.1", m_handler.getRequestFirstHeader());
673
674 request.setUrl(m_handler.getURL());
675 final HTTPResponse response2 = request.PUT("/foo");
676 assertEquals(200, response2.getStatusCode());
677 assertEquals("PUT /foo HTTP/1.1", m_handler.getRequestFirstHeader());
678
679 final HTTPResponse response3 = request.PUT();
680 assertEquals(200, response3.getStatusCode());
681 assertEquals("PUT / HTTP/1.1", m_handler.getRequestFirstHeader());
682
683 final byte[] data4 = randomBytes(10);
684
685 final HTTPResponse response4 = request.PUT("/blah", data4);
686 assertEquals(200, response4.getStatusCode());
687 assertEquals("PUT /blah HTTP/1.1", m_handler.getRequestFirstHeader());
688 assertArraysEqual(data4, m_handler.getLastRequestBody());
689
690 final byte[] data5 = randomBytes(100);
691
692 request.setUrl(m_handler.getURL() + "/lah/");
693 request.setData(data5);
694 final HTTPResponse response5 = request.PUT("/blah");
695 assertEquals(200, response5.getStatusCode());
696 assertEquals("PUT /blah HTTP/1.1", m_handler.getRequestFirstHeader());
697 assertArraysEqual(data5, m_handler.getLastRequestBody());
698
699 final NVPair[] headers6 = {
700 new NVPair("key", "value"),
701 };
702
703 request.setHeaders(headers6);
704 final HTTPResponse response6 = request.PUT();
705 assertEquals(200, response6.getStatusCode());
706 assertEquals("PUT /lah/ HTTP/1.1", m_handler.getRequestFirstHeader());
707 m_handler.assertRequestContainsHeader("key: value");
708
709 final byte[] data7 = randomBytes(10000);
710
711 final HTTPResponse response7 = request.PUT("/bhhh",
712 new ByteArrayInputStream(data7));
713 assertEquals(200, response7.getStatusCode());
714 assertEquals("PUT /bhhh HTTP/1.1", m_handler.getRequestFirstHeader());
715 assertArraysEqual(data7, m_handler.getLastRequestBody());
716 }
717
718 @Test public void testTRACE() throws Exception {
719 final HTTPRequest request = new HTTPRequest();
720
721 try {
722 request.TRACE();
723 fail("Expected URLException");
724 }
725 catch (final URLException e) {
726 }
727
728 try {
729 request.TRACE("??partial");
730 fail("Expected URLException");
731 }
732 catch (final URLException e) {
733 }
734
735 final HTTPResponse response = request.TRACE(m_handler.getURL());
736 assertEquals(200, response.getStatusCode());
737 assertEquals("TRACE / HTTP/1.1", m_handler.getRequestFirstHeader());
738
739 request.setUrl(m_handler.getURL());
740 final HTTPResponse response2 = request.TRACE("/foo");
741 assertEquals(200, response2.getStatusCode());
742 assertEquals("TRACE /foo HTTP/1.1", m_handler.getRequestFirstHeader());
743
744 final HTTPResponse response3 = request.TRACE();
745 assertEquals(200, response3.getStatusCode());
746 assertEquals("TRACE / HTTP/1.1", m_handler.getRequestFirstHeader());
747
748 final NVPair[] headers4 = {
749 new NVPair("key", "value"),
750 };
751
752 request.setUrl(m_handler.getURL() + "/lah/");
753 request.setHeaders(headers4);
754 final HTTPResponse response4 = request.TRACE();
755 assertEquals(200, response4.getStatusCode());
756 assertEquals("TRACE /lah/ HTTP/1.1", m_handler.getRequestFirstHeader());
757 m_handler.assertRequestContainsHeader("key: value");
758 }
759
760 @Test public void testToString() throws Exception {
761 final HTTPRequest request = new HTTPRequest();
762
763 assertEquals("<Undefined URL>\n", request.toString());
764
765 request.setUrl("http://grinder.sf.net/");
766 assertEquals("http://grinder.sf.net/\n", request.toString());
767
768 request.setHeaders(new NVPair[] {
769 new NVPair("home", "end"),
770 new NVPair("pause", "insert"),
771 });
772
773 assertEquals("http://grinder.sf.net/\nhome: end\npause: insert\n",
774 request.toString());
775 }
776
777 @Test public void testSetDataFromFile() throws Exception {
778
779 final File file = File.createTempFile("testing", "123");
780 file.deleteOnExit();
781
782 final OutputStream out = new FileOutputStream(file);
783
784 final byte[] data5 = randomBytes(10);
785
786 out.write(data5);
787 out.close();
788
789 final HTTPRequest request = new HTTPRequest();
790 request.setDataFromFile(file.getPath());
791
792 assertArraysEqual(data5, request.getData());
793
794 }
795
796 @Test public void testResponseProcessing() throws Exception {
797 final HTTPRequest request = new HTTPRequest();
798 request.GET(m_handler.getURL());
799
800 verify(m_logger).info(m_stringCaptor.capture());
801
802 final String message = m_stringCaptor.getValue();
803 assertTrue(message.indexOf("200") >= 0);
804 assertEquals(-1, message.indexOf("Redirect"));
805
806 verify(m_statistics).isTestInProgress();
807 verifyNoMoreInteractions(m_statistics);
808 }
809
810 @Test public void testRedirectResponseProcessing() throws Exception {
811
812 final int[] redirectCodes = {
813 302,
814 HttpURLConnection.HTTP_MOVED_PERM,
815 HttpURLConnection.HTTP_MOVED_TEMP,
816 307,
817 };
818
819 for (final int redirectCode : redirectCodes) {
820 final HTTPRequestHandler handler = new HTTPRequestHandler() {
821 @Override
822 protected void writeHeaders(final StringBuffer response) {
823 response.append("HTTP/1.0 ");
824 response.append(redirectCode);
825 response.append(" Moved Temporarily\r\n");
826 }
827 };
828 handler.start();
829
830 when(m_statistics.isTestInProgress()).thenReturn(true);
831 when(m_statistics.getForCurrentTest()).thenReturn(m_statisticsForTest);
832
833 final HTTPRequest request = new HTTPRequest();
834 final HTTPResponse response = request.GET(handler.getURL());
835 assertNotNull(response);
836
837 verify(m_logger, atLeastOnce()).info(m_stringCaptor.capture());
838 final String message = m_stringCaptor.getValue();
839
840 assertTrue(message.indexOf(Integer.toString(redirectCode)) >= 0);
841 assertTrue(message.indexOf("Redirect") >= 0);
842
843 handler.shutdown();
844 }
845 }
846
847 @Test public void testBadRequestResponseProcessing() throws Exception {
848 final HTTPRequestHandler handler = new HTTPRequestHandler() {
849 @Override
850 protected void writeHeaders(final StringBuffer response) {
851 response.append("HTTP/1.0 400 Bad Request\r\n");
852 }
853 };
854
855 handler.start();
856
857 when(m_statistics.isTestInProgress()).thenReturn(true);
858 when(m_statistics.getForCurrentTest()).thenReturn(m_statisticsForTest);
859
860 final HTTPRequest request = new HTTPRequest();
861 final HTTPResponse response = request.GET(handler.getURL());
862 assertNotNull(response);
863
864 verify(m_logger).info(m_stringCaptor.capture());
865 final String message = m_stringCaptor.getValue();
866 assertTrue(message.indexOf("400") >= 0);
867
868 handler.shutdown();
869 }
870
871 @Test public void testSubclassProcessResponse() throws Exception {
872 final Object[] resultHolder = new Object[1];
873
874 final HTTPRequest request = new HTTPRequest() {
875 @Override
876 public void processResponse(final HTTPResponse response) {
877 resultHolder[0] = response;
878 }
879 };
880
881 final HTTPResponse response = request.GET(m_handler.getURL());
882
883 assertSame(response, resultHolder[0]);
884 }
885
886 @Test public void testConnectionTimingsAndStatistics() throws Exception {
887
888 final ListTimeAuthority timeAuthority =
889 new ListTimeAuthority(new long[] {
890 100,
891 101,
892 123,
893 200,
894 219,
895 });
896
897 final HTTPPluginThreadState threadState =
898 new HTTPPluginThreadState(m_threadContext,
899 m_sslContextFactory,
900 null,
901 timeAuthority);
902
903 when(m_pluginProcessContext.getPluginThreadListener())
904 .thenReturn(threadState);
905
906 when(m_statistics.isTestInProgress()).thenReturn(true);
907 when(m_statistics.getForCurrentTest()).thenReturn(m_statisticsForTest);
908
909 final HTTPRequest request = new HTTPRequest();
910 final String bodyText = "Your heart's gone the colour of Coca Cola\n";
911 m_handler.setBody(bodyText);
912 final HTTPResponse response = request.GET(m_handler.getURL());
913 assertEquals(200, response.getStatusCode());
914 assertEquals("GET / HTTP/1.1", m_handler.getRequestFirstHeader());
915
916 verify(m_statisticsForTest)
917 .addLong(StatisticsIndexMap.HTTP_PLUGIN_RESPONSE_LENGTH_KEY,
918 bodyText.length());
919 verify(m_statisticsForTest)
920 .setLong(StatisticsIndexMap.HTTP_PLUGIN_RESPONSE_STATUS_KEY, 200);
921 verify(m_statisticsForTest)
922 .addLong(StatisticsIndexMap.HTTP_PLUGIN_DNS_TIME_KEY, 22);
923 verify(m_statisticsForTest)
924 .addLong(StatisticsIndexMap.HTTP_PLUGIN_CONNECT_TIME_KEY, 99);
925 verify(m_statisticsForTest)
926 .addLong(StatisticsIndexMap.HTTP_PLUGIN_FIRST_BYTE_TIME_KEY, 119);
927 verify(m_statisticsForTest)
928 .addLong(StatisticsIndexMap.HTTP_PLUGIN_CONNECTIONS_ESTABLISHED, 1);
929 verifyNoMoreInteractions(m_statisticsForTest);
930
931 try {
932 timeAuthority.getTimeInMilliseconds();
933 fail("Not all times used");
934 }
935 catch (final ArrayIndexOutOfBoundsException e) {
936 }
937
938 assertTrue(response.getInputStream() instanceof ByteArrayInputStream);
939 assertEquals(bodyText, response.getText());
940 }
941
942 @Test public void testConnectionTimingsAndStatisticsInvalidTimes()
943 throws Exception {
944
945 final ListTimeAuthority timeAuthority =
946 new ListTimeAuthority(new long[] {
947 400,
948 400,
949 0,
950 0,
951 419,
952 });
953
954 final HTTPPluginThreadState threadState =
955 new HTTPPluginThreadState(m_threadContext,
956 m_sslContextFactory,
957 null,
958 timeAuthority);
959
960 when(m_pluginProcessContext.getPluginThreadListener())
961 .thenReturn(threadState);
962
963 when(m_statistics.isTestInProgress()).thenReturn(true);
964 when(m_statistics.getForCurrentTest()).thenReturn(m_statisticsForTest);
965
966 m_handler.setBody(null);
967
968 final HTTPRequest request = new HTTPRequest();
969 final HTTPResponse response = request.GET(m_handler.getURL());
970 assertEquals(200, response.getStatusCode());
971 assertEquals("GET / HTTP/1.1", m_handler.getRequestFirstHeader());
972
973 verify(m_statisticsForTest)
974 .addLong(StatisticsIndexMap.HTTP_PLUGIN_RESPONSE_LENGTH_KEY, 0);
975 verify(m_statisticsForTest)
976 .setLong(StatisticsIndexMap.HTTP_PLUGIN_RESPONSE_STATUS_KEY, 200);
977 verify(m_statisticsForTest)
978 .addLong(StatisticsIndexMap.HTTP_PLUGIN_DNS_TIME_KEY, 0);
979 verify(m_statisticsForTest)
980 .addLong(StatisticsIndexMap.HTTP_PLUGIN_CONNECT_TIME_KEY, 0);
981 verify(m_statisticsForTest)
982 .addLong(StatisticsIndexMap.HTTP_PLUGIN_FIRST_BYTE_TIME_KEY, 19);
983 verify(m_statisticsForTest)
984 .addLong(StatisticsIndexMap.HTTP_PLUGIN_CONNECTIONS_ESTABLISHED, 1);
985 verifyNoMoreInteractions(m_statisticsForTest);
986
987 try {
988 timeAuthority.getTimeInMilliseconds();
989 fail("Not all times used");
990 }
991 catch (final ArrayIndexOutOfBoundsException e) {
992 }
993
994 assertTrue(response.getInputStream() instanceof ByteArrayInputStream);
995 assertEquals("", response.getText());
996 }
997
998 @Test public void testSetReadResponseBody() throws Exception {
999
1000 final ListTimeAuthority timeAuthority =
1001 new ListTimeAuthority(new long[] {
1002 100,
1003 110,
1004 123,
1005 200,
1006 219,
1007 });
1008
1009 final HTTPPluginThreadState threadState =
1010 new HTTPPluginThreadState(m_threadContext,
1011 m_sslContextFactory,
1012 null,
1013 timeAuthority);
1014
1015 when(m_pluginProcessContext.getPluginThreadListener())
1016 .thenReturn(threadState);
1017
1018 when(m_statistics.isTestInProgress()).thenReturn(true);
1019 when(m_statistics.getForCurrentTest()).thenReturn(m_statisticsForTest);
1020
1021 final HTTPRequest request = new HTTPRequest();
1022
1023 assertTrue(request.getReadResponseBody());
1024 request.setReadResponseBody(false);
1025 assertFalse(request.getReadResponseBody());
1026 request.setReadResponseBody(true);
1027 assertTrue(request.getReadResponseBody());
1028 request.setReadResponseBody(false);
1029 assertFalse(request.getReadResponseBody());
1030
1031 final String bodyText =
1032 "Your heart's gone the colour of a dust\nbin\n liner";
1033 m_handler.setBody(bodyText);
1034
1035 final HTTPResponse response = request.GET(m_handler.getURL());
1036 assertEquals(200, response.getStatusCode());
1037 assertEquals("GET / HTTP/1.1", m_handler.getRequestFirstHeader());
1038
1039 verify(m_statisticsForTest)
1040 .addLong(StatisticsIndexMap.HTTP_PLUGIN_RESPONSE_LENGTH_KEY, 0);
1041 verify(m_statisticsForTest)
1042 .setLong(StatisticsIndexMap.HTTP_PLUGIN_RESPONSE_STATUS_KEY, 200);
1043 verify(m_statisticsForTest)
1044 .addLong(StatisticsIndexMap.HTTP_PLUGIN_DNS_TIME_KEY, 13);
1045 verify(m_statisticsForTest)
1046 .addLong(StatisticsIndexMap.HTTP_PLUGIN_CONNECT_TIME_KEY, 90);
1047 verify(m_statisticsForTest)
1048 .addLong(StatisticsIndexMap.HTTP_PLUGIN_FIRST_BYTE_TIME_KEY, 119);
1049 verify(m_statisticsForTest)
1050 .addLong(StatisticsIndexMap.HTTP_PLUGIN_CONNECTIONS_ESTABLISHED, 1);
1051 verifyNoMoreInteractions(m_statisticsForTest);
1052
1053 try {
1054 timeAuthority.getTimeInMilliseconds();
1055 fail("Not all times used");
1056 }
1057 catch (final ArrayIndexOutOfBoundsException e) {
1058 }
1059 }
1060
1061 @Test public void testWithBadStatistics() throws Exception {
1062
1063 when(m_statistics.isTestInProgress()).thenReturn(true);
1064 when(m_statistics.getForCurrentTest()).thenReturn(m_statisticsForTest);
1065
1066 final Exception exception = new InvalidContextException("bah");
1067
1068 doThrow(exception)
1069 .when(m_statisticsForTest).addLong(isA(String.class), isA(Long.class));
1070
1071 final HTTPRequest request = new HTTPRequest();
1072
1073 try {
1074 request.GET(m_handler.getURL());
1075 fail("Expected PluginException");
1076 }
1077 catch (final PluginException e) {
1078 assertSame(exception, e.getCause());
1079 }
1080 }
1081
1082 @Test public void testConnectionClose() throws Exception {
1083 final HTTPRequest request = new HTTPRequest();
1084
1085 final HTTPResponse response = request.GET(m_handler.getURL());
1086 assertEquals(200, response.getStatusCode());
1087 assertEquals("GET / HTTP/1.1", m_handler.getRequestFirstHeader());
1088
1089 HTTPPluginControl.getThreadConnection(m_handler.getURL()).close();
1090
1091 final HTTPResponse response2 = request.GET(m_handler.getURL());
1092 assertEquals(200, response2.getStatusCode());
1093 assertEquals("GET / HTTP/1.1", m_handler.getRequestFirstHeader());
1094 }
1095
1096 @Test public void testDCRInstrumentation() throws Exception {
1097 final HTTPRequest request = new HTTPRequest();
1098
1099 final Instrumenter instrumenter =
1100 new JavaScriptEngineService(DCRContextImplementation.create(null))
1101 .createInstrumenters().get(0);
1102
1103 final Recorder recorder = mock(Recorder.class);
1104
1105 final net.grinder.common.Test test = mock(net.grinder.common.Test.class);
1106
1107 instrumenter.instrument(test, recorder, request,
1108 HTTPRequest.getHttpMethodFilter());
1109 verifyNoMoreInteractions(recorder);
1110
1111 try {
1112 request.GET();
1113 fail("Expected URLException");
1114 }
1115 catch (final URLException e) {
1116 }
1117
1118
1119 verify(recorder, times(3)).start();
1120 verify(recorder, times(3)).end(false);
1121 verifyNoMoreInteractions(recorder);
1122
1123 try {
1124 request.GET("#partial");
1125 fail("Expected URLException");
1126 }
1127 catch (final URLException e) {
1128 }
1129
1130
1131 verify(recorder, times(5)).start();
1132 verify(recorder, times(5)).end(false);
1133 verifyNoMoreInteractions(recorder);
1134
1135 final HTTPResponse response = request.GET(m_handler.getURL());
1136 assertEquals(200, response.getStatusCode());
1137 assertEquals("GET / HTTP/1.1", m_handler.getRequestFirstHeader());
1138
1139 verify(recorder, times(7)).start();
1140 verify(recorder, times(2)).end(true);
1141 verifyNoMoreInteractions(recorder);
1142 }
1143
1144 @Test public void testReadTimeout() throws Exception {
1145
1146 final HTTPRequestHandler httpServer = new HTTPRequestHandler();
1147 httpServer.setResponseDelay(100);
1148 httpServer.start();
1149
1150 final HTTPPluginConnectionDefaults connectionDefaults =
1151 HTTPPluginConnectionDefaults.getConnectionDefaults();
1152
1153 final int originalTimeout = connectionDefaults.getTimeout();
1154
1155 try {
1156 connectionDefaults.setTimeout(1);
1157
1158 try {
1159 new HTTPRequest().GET(httpServer.getURL());
1160 fail("Expected TimeoutException");
1161 }
1162 catch (final TimeoutException e) {
1163 }
1164
1165
1166
1167 final HTTPRequestHandler httpServer2 = new HTTPRequestHandler();
1168 httpServer2.setResponseDelay(100);
1169 httpServer2.start();
1170
1171 final HTTPPluginConnection connection =
1172 HTTPPluginControl.getThreadConnection(httpServer2.getURL());
1173
1174 connection.setTimeout(0);
1175 final HTTPResponse response = new HTTPRequest().GET(httpServer2.getURL());
1176 assertEquals("", response.getText());
1177
1178 connection.setTimeout(1);
1179
1180 try {
1181 new HTTPRequest().GET(httpServer2.getURL());
1182 fail("Expected TimeoutException");
1183 }
1184 catch (final TimeoutException e) {
1185 }
1186
1187 connection.close();
1188 }
1189 finally {
1190 connectionDefaults.setTimeout(originalTimeout);
1191 }
1192 }
1193
1194 @Test public void testNullHeaders() throws Exception {
1195 try {
1196 new HTTPRequest().GET(m_handler.getURL(), null, null);
1197 }
1198 catch (final NullPointerException e) {
1199 assertContains(e.getMessage(), "headers");
1200 }
1201 }
1202
1203 @Test public void testNullHeader() throws Exception {
1204
1205 final NVPair[] headers = { new NVPair("a", "b"),
1206 null };
1207
1208 try {
1209 new HTTPRequest().GET(m_handler.getURL(), null, headers);
1210 }
1211 catch (final NullPointerException e) {
1212 assertContains(e.getMessage(), "headers[1]");
1213 }
1214 }
1215
1216 @Test public void testNullHeaderName() throws Exception {
1217
1218 final NVPair[] headers = { new NVPair("a", "b"),
1219 new NVPair(null, "123") };
1220
1221 try {
1222 new HTTPRequest().GET(m_handler.getURL(), null, headers);
1223 }
1224 catch (final NullPointerException e) {
1225 assertContains(e.getMessage(), "headers[1].getName()");
1226 }
1227 }
1228
1229 private static byte[] randomBytes(final int max) {
1230 final byte[] result = new byte[s_random.nextInt(max)];
1231 s_random.nextBytes(result);
1232 return result;
1233 }
1234
1235 private static class ListTimeAuthority implements TimeAuthority {
1236
1237 private long[] m_times;
1238 private int m_last;
1239
1240 ListTimeAuthority(final long[] times) {
1241 setTimes(times);
1242 }
1243
1244 public void setTimes(final long[] times) {
1245 m_times = times;
1246 m_last = -1;
1247 }
1248
1249 @Override
1250 public long getTimeInMilliseconds() {
1251 return m_times[++m_last];
1252 }
1253 }
1254 }