1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 package net.grinder.plugin.http.tcpproxyfilter;
25
26 import static org.junit.Assert.assertEquals;
27 import static org.junit.Assert.assertFalse;
28 import static org.junit.Assert.assertTrue;
29 import static org.mockito.Matchers.contains;
30 import static org.mockito.Matchers.eq;
31 import static org.mockito.Matchers.isA;
32 import static org.mockito.Matchers.same;
33 import static org.mockito.Mockito.times;
34 import static org.mockito.Mockito.verify;
35 import static org.mockito.Mockito.verifyNoMoreInteractions;
36 import static org.mockito.Mockito.when;
37
38 import java.io.File;
39 import java.io.FileNotFoundException;
40 import java.nio.BufferOverflowException;
41
42 import net.grinder.plugin.http.xml.FormFieldType;
43 import net.grinder.plugin.http.xml.RequestType;
44 import net.grinder.plugin.http.xml.ResponseTokenReferenceType;
45 import net.grinder.plugin.http.xml.TokenReferenceType;
46 import net.grinder.plugin.http.xml.TokenResponseLocationType;
47 import net.grinder.plugin.http.xml.TokenType;
48 import net.grinder.testutility.AbstractJUnit4FileTestCase;
49 import net.grinder.testutility.FileUtilities;
50 import net.grinder.tools.tcpproxy.CommentSource;
51 import net.grinder.tools.tcpproxy.CommentSourceImplementation;
52 import net.grinder.tools.tcpproxy.ConnectionDetails;
53 import net.grinder.tools.tcpproxy.EndPoint;
54 import net.grinder.util.AttributeStringParser;
55 import net.grinder.util.AttributeStringParserImplementation;
56 import net.grinder.util.SimpleStringEscaper;
57 import net.grinder.util.StringEscaper;
58 import net.grinder.util.http.URIParser;
59 import net.grinder.util.http.URIParserImplementation;
60
61 import org.junit.Before;
62 import org.junit.Test;
63 import org.mockito.ArgumentCaptor;
64 import org.mockito.Captor;
65 import org.mockito.Mock;
66 import org.mockito.MockitoAnnotations;
67 import org.slf4j.Logger;
68
69
70
71
72
73
74
75 public class TestConnectionHandlerImplementation
76 extends AbstractJUnit4FileTestCase {
77
78 @Mock private HTTPRecording m_httpRecording;
79 @Mock private Logger m_logger;
80 @Captor private ArgumentCaptor<ResponseTokenReferenceType>
81 m_responseTokenRTCaptor;
82
83 private final RegularExpressions m_regularExpressions =
84 new RegularExpressionsImplementation();
85
86 private final URIParser m_uriParser = new URIParserImplementation();
87
88 private final AttributeStringParser m_attributeStringParser =
89 new AttributeStringParserImplementation();
90
91 private StringEscaper m_stringEscaper = new SimpleStringEscaper();
92
93 private final ConnectionDetails m_connectionDetails =
94 new ConnectionDetails(
95 new EndPoint("hostA", 80),
96 new EndPoint("hostB", 80),
97 false);
98
99 private final CommentSource m_commentSource =
100 new CommentSourceImplementation();
101
102 @Before public void setUp() {
103 MockitoAnnotations.initMocks(this);
104
105 final HTTPRecordingParameters parametersFromProperties =
106 new ParametersFromProperties();
107
108 when(m_httpRecording.getParameters()).thenReturn(parametersFromProperties);
109 }
110
111 @Test public void testRequestWithGet() throws Exception {
112 final ConnectionHandler handler =
113 new ConnectionHandlerImplementation(
114 m_httpRecording, m_logger, m_regularExpressions,
115 m_uriParser, m_attributeStringParser, null,
116 m_commentSource, m_connectionDetails);
117
118 final RequestType request = RequestType.Factory.newInstance();
119 request.addNewHeaders();
120 request.setMethod(RequestType.Method.Enum.forString("GET"));
121
122 final TokenType token = TokenType.Factory.newInstance();
123 token.setName("query");
124 token.setTokenId("tokenID");
125
126 when(m_httpRecording.addRequest(m_connectionDetails,
127 "GET",
128 "/something?query=whatever"))
129 .thenReturn(request);
130
131 final String message = "GET /something?query=whatever HTTP/1.0\r\n\r\n";
132 final byte[] buffer = message.getBytes();
133 handler.handleRequest(buffer, buffer.length);
134
135 final String response = "HTTP/1.0 200 OK\r\n";
136 final byte[] responseBuffer = response.getBytes();
137
138 handler.handleResponse(responseBuffer, responseBuffer.length);
139
140 verify(m_httpRecording).markLastResponseTime();
141
142 handler.requestFinished();
143 }
144
145 @Test public void testAuthorization() throws Exception {
146 final ConnectionHandler handler =
147 new ConnectionHandlerImplementation(
148 m_httpRecording, m_logger, m_regularExpressions,
149 m_uriParser, m_attributeStringParser, null,
150 m_commentSource, m_connectionDetails);
151
152 final RequestType request = RequestType.Factory.newInstance();
153 request.addNewHeaders();
154 request.setMethod(RequestType.Method.Enum.forString("GET"));
155
156 when(m_httpRecording.addRequest(m_connectionDetails,
157 "GET",
158 "/"))
159 .thenReturn(request);
160
161 final String message =
162 "GET / HTTP/1.1\r\n" +
163 "Authorization: Basic aBcD\r\n";
164 final byte[] buffer = message.getBytes();
165 handler.handleRequest(buffer, buffer.length);
166
167
168 verify(m_logger).error(isA(String.class));
169 assertEquals(0, request.getHeaders().sizeOfAuthorizationArray());
170
171 final String message2 =
172 "GET / HTTP/1.1\r\n" +
173 "Authorization: Basic dDpyYXVtc2NobWllcmU=\r\n";
174 final byte[] buffer2 = message2.getBytes();
175 handler.handleRequest(buffer2, buffer2.length);
176
177 assertEquals("t", request.getHeaders().getAuthorizationArray(0).getBasic().getUserid());
178 assertEquals("raumschmiere", request.getHeaders().getAuthorizationArray(0).getBasic().getPassword());
179 }
180
181 @Test public void testRequestWithPost() throws Exception {
182 final ConnectionHandler handler =
183 new ConnectionHandlerImplementation(
184 m_httpRecording, m_logger, m_regularExpressions,
185 m_uriParser, m_attributeStringParser, m_stringEscaper, m_commentSource,
186 m_connectionDetails);
187
188 final RequestType request = RequestType.Factory.newInstance();
189 request.addNewHeaders();
190 request.setMethod(RequestType.Method.Enum.forString("POST"));
191
192 when(m_httpRecording.addRequest(same(m_connectionDetails),
193 eq("POST"),
194 isA(String.class)))
195 .thenReturn(request);
196
197
198 final String message =
199 "POST /something HTTP/1.0\r\n" +
200 "Content-Length: 10\r\n" +
201 "Content-Type: bah\r\n" +
202 "\r\n" +
203 "0123456789";
204
205 final byte[] buffer = message.getBytes();
206 handler.handleRequest(buffer, buffer.length);
207
208 final String response = "HTTP/1.0 200 OK\r\n";
209 final byte[] responseBuffer = response.getBytes();
210
211 handler.handleResponse(responseBuffer, responseBuffer.length);
212
213 verify(m_httpRecording).markLastResponseTime();
214
215 final String message2 =
216 "POST /more HTTP/1.0\r\n" +
217 "Content-Length: 10\r\n" +
218 "\r\n";
219
220 final byte[] buffer2 = message2.getBytes();
221 handler.handleRequest(buffer2, buffer2.length);
222
223 final String message3 = "0123456789";
224 final byte[] buffer3 = message3.getBytes();
225 handler.handleRequest(buffer3, buffer3.length);
226
227 final String message4 =
228 "POST /evenmore HTTP/1.0\r\n";
229
230 final byte[] buffer4 = message4.getBytes();
231 handler.handleRequest(buffer4, buffer4.length);
232
233 final String message5 =
234 "Content-Length: 0\r\n" +
235 "\r\n";
236
237 final byte[] buffer5 = message5.getBytes();
238 handler.handleRequest(buffer5, buffer5.length);
239
240 verify(m_httpRecording, times(3)).addRequest(same(m_connectionDetails),
241 eq("POST"),
242 isA(String.class));
243 }
244
245 @Test public void testResponseMessage1() throws Exception {
246 final ConnectionHandler handler =
247 new ConnectionHandlerImplementation(
248 m_httpRecording, m_logger, m_regularExpressions,
249 m_uriParser, m_attributeStringParser, null, m_commentSource, m_connectionDetails);
250
251 final RequestType request = RequestType.Factory.newInstance();
252 request.addNewHeaders();
253 request.setMethod(RequestType.Method.Enum.forString("HEAD"));
254
255 when (m_httpRecording.addRequest(m_connectionDetails,
256 "HEAD",
257 "/"))
258 .thenReturn(request);
259
260 final String message = "HEAD / HTTP/1.1\r\n";
261 final byte[] buffer = message.getBytes();
262 handler.handleRequest(buffer, buffer.length);
263
264 final String response =
265 "HTTP/1.0 302 Redirect\r\n" +
266 "Hello: world\r\n" +
267 "Location: http://somewhere/;a=b?c=d\r\n";
268
269 final byte[] responseBuffer = response.getBytes();
270 handler.handleResponse(responseBuffer, responseBuffer.length);
271
272 verify(m_httpRecording).markLastResponseTime();
273
274 verify(m_httpRecording)
275 .setTokenReference(eq("a"),
276 eq("b"),
277 isA(ResponseTokenReferenceType.class));
278
279 verify(m_httpRecording)
280 .setTokenReference(eq("c"),
281 eq("d"),
282 isA(ResponseTokenReferenceType.class));
283 }
284
285 @Test public void testResponseMessage2() throws Exception {
286 final ConnectionHandler handler =
287 new ConnectionHandlerImplementation(
288 m_httpRecording, m_logger, m_regularExpressions,
289 m_uriParser, m_attributeStringParser, null,
290 m_commentSource, m_connectionDetails);
291
292 final RequestType request = RequestType.Factory.newInstance();
293 request.addNewHeaders();
294 request.setMethod(RequestType.Method.Enum.forString("GET"));
295
296 when(m_httpRecording.addRequest(m_connectionDetails,
297 "GET",
298 "/"))
299 .thenReturn(request);
300
301 final String message = "GET / HTTP/1.1\r\n";
302 final byte[] buffer = message.getBytes();
303 handler.handleRequest(buffer, buffer.length);
304
305 final String response =
306 "HTTP/1.0 200 OK\r\n" +
307 "Content-Length:10\r\n\r\n" +
308 "0123456789";
309
310 final byte[] responseBuffer = response.getBytes();
311 handler.handleResponse(responseBuffer, responseBuffer.length);
312
313 verify(m_httpRecording).markLastResponseTime();
314 }
315
316 @Test public void testResponseMessage3() throws Exception {
317 final ConnectionHandler handler =
318 new ConnectionHandlerImplementation(
319 m_httpRecording, m_logger, m_regularExpressions,
320 m_uriParser, m_attributeStringParser, null, m_commentSource, m_connectionDetails);
321
322 final RequestType request = RequestType.Factory.newInstance();
323 request.addNewHeaders();
324 request.setMethod(RequestType.Method.Enum.forString("GET"));
325
326 when(m_httpRecording.addRequest(m_connectionDetails, "GET", "/"))
327 .thenReturn(request);
328
329 final String message = "GET / HTTP/1.1\r\n";
330 final byte[] buffer = message.getBytes();
331 handler.handleRequest(buffer, buffer.length);
332
333 final String response =
334 "HTTP/1.0 304 Not Modified\r\n";
335
336 final byte[] responseBuffer = response.getBytes();
337 handler.handleResponse(responseBuffer, responseBuffer.length);
338
339 verify(m_httpRecording).markLastResponseTime();
340 }
341
342 @Test public void testResponseMessageWithTokensInLinks() throws Exception {
343 final ConnectionHandler handler =
344 new ConnectionHandlerImplementation(
345 m_httpRecording, m_logger, m_regularExpressions,
346 m_uriParser, m_attributeStringParser, null,
347 m_commentSource, m_connectionDetails);
348
349 final RequestType request = RequestType.Factory.newInstance();
350 request.addNewHeaders();
351 request.setMethod(RequestType.Method.Enum.forString("GET"));
352
353 when(m_httpRecording.addRequest(m_connectionDetails, "GET", "/"))
354 .thenReturn(request);
355 when(m_httpRecording.getLastValueForToken(isA(String.class)))
356 .thenReturn("1");
357
358 final String message = "GET / HTTP/1.0\r\n";
359 final byte[] buffer = message.getBytes();
360 handler.handleRequest(buffer, buffer.length);
361
362 final String response =
363 "HTTP/1.0 200 OK\r\n" +
364 "\r\n" +
365 "<html>" +
366 "<body><a href='./foo;session=57?token=1'>Hello world</a>" +
367 "<a href=\"http://grinder.sourceforge.net/?token=1\">something else</a>";
368
369 final byte[] responseBuffer = response.getBytes();
370 handler.handleResponse(responseBuffer, responseBuffer.length);
371
372 verify(m_httpRecording).markLastResponseTime();
373
374 final String response2 =
375 "<a href=\"http://grinder.sourceforge.net/?token=2\">something else</a>" +
376 "</body>";
377 final byte[] responseBuffer2 = response2.getBytes();
378 handler.handleResponse(responseBuffer2, responseBuffer2.length);
379
380
381 handler.requestFinished();
382
383 verify(m_httpRecording)
384 .setTokenReference(eq("session"),
385 eq("57"),
386 m_responseTokenRTCaptor.capture());
387
388 assertEquals(TokenResponseLocationType.RESPONSE_BODY_URI_PATH_PARAMETER.toString(),
389 m_responseTokenRTCaptor.getValue().getSource());
390
391 verify(m_httpRecording)
392 .setTokenReference(eq("token"),
393 eq("1"),
394 m_responseTokenRTCaptor.capture());
395
396 final ResponseTokenReferenceType responseTokenReference2 =
397 m_responseTokenRTCaptor.getValue();
398 assertEquals(1, responseTokenReference2.getConflictingValueArray().length);
399 assertEquals("2", responseTokenReference2.getConflictingValueArray()[0].getValue());
400 assertEquals(TokenResponseLocationType.RESPONSE_BODY_URI_QUERY_STRING.toString(),
401 responseTokenReference2.getConflictingValueArray()[0].getSource());
402
403 verify(m_httpRecording, times(2)).getLastValueForToken(isA(String.class));
404 }
405
406 @Test public void testResponseMessageWithTokensInHiddenParameters() throws Exception {
407 final ConnectionHandler handler =
408 new ConnectionHandlerImplementation(
409 m_httpRecording, m_logger, m_regularExpressions,
410 m_uriParser, m_attributeStringParser, null, m_commentSource, m_connectionDetails);
411
412 final RequestType request = RequestType.Factory.newInstance();
413 request.addNewHeaders();
414 request.setMethod(RequestType.Method.Enum.forString("GET"));
415
416 when(m_httpRecording.addRequest(m_connectionDetails, "GET", "/"))
417 .thenReturn(request);
418
419 final String message = "GET / HTTP/1.0\r\n";
420 final byte[] buffer = message.getBytes();
421 handler.handleRequest(buffer, buffer.length);
422
423 final String response =
424 "HTTP/1.0 200 OK\r\n" +
425 "\r\n" +
426 "<html>" +
427 "<body><form>\n\n<input name=\"foo\" value=\"123\" \n" +
428 " type=\"HIDDEN\">" +
429 "<input type='hidden' name='blah'/>" +
430 "</form>" +
431 "</body></html>";
432
433 final byte[] responseBuffer = response.getBytes();
434 handler.handleResponse(responseBuffer, responseBuffer.length);
435
436 verify(m_httpRecording).markLastResponseTime();
437
438 handler.requestFinished();
439
440 verify(m_httpRecording)
441 .setTokenReference(eq("foo"),
442 eq("123"),
443 m_responseTokenRTCaptor.capture());
444
445 assertEquals(TokenResponseLocationType.RESPONSE_BODY_HIDDEN_INPUT.toString(),
446 m_responseTokenRTCaptor.getValue().getSource());
447 }
448
449 @Test public void testRequestStringBody() throws Exception {
450 final ConnectionHandler handler =
451 new ConnectionHandlerImplementation(
452 m_httpRecording, m_logger, m_regularExpressions,
453 m_uriParser, m_attributeStringParser, m_stringEscaper,
454 m_commentSource, m_connectionDetails);
455
456 final RequestType request = RequestType.Factory.newInstance();
457 request.addNewHeaders();
458 request.setMethod(RequestType.Method.Enum.forString("POST"));
459
460 when(m_httpRecording.addRequest(m_connectionDetails, "POST", "/something"))
461 .thenReturn(request);
462
463 final String message =
464 "POST /something HTTP/1.0\r\n" +
465 "Content-Length: 9\r\n" +
466 "Content-Type: bah\r\n" +
467 "\r\n" +
468 "0123456789";
469
470 final byte[] buffer = message.getBytes();
471 handler.handleRequest(buffer, buffer.length);
472
473 verify(m_logger).error(contains("content length exceeded"));
474
475 handler.requestFinished();
476
477 assertEquals("bah", request.getBody().getContentType());
478 assertEquals("012345678", request.getBody().getEscapedString());
479 assertFalse(request.getBody().isSetBinary());
480 assertFalse(request.getBody().isSetFile());
481 assertFalse(request.getBody().isSetForm());
482 }
483
484 @Test public void testRequestWithUserComment() throws Exception {
485 ConnectionHandler handler = new ConnectionHandlerImplementation(
486 m_httpRecording, m_logger, m_regularExpressions,
487 m_uriParser, m_attributeStringParser, null,
488 m_commentSource, m_connectionDetails);
489
490
491
492 ((CommentSourceImplementation)m_commentSource).addComment("user comment 1");
493 ((CommentSourceImplementation)m_commentSource).addComment("user comment 2");
494
495 final RequestType request = RequestType.Factory.newInstance();
496
497 request.addNewHeaders();
498 request.setMethod(RequestType.Method.Enum.forString("GET"));
499 request.setCommentArray(new String[]{"user comment 1", "user comment 2"});
500
501 final TokenType token = TokenType.Factory.newInstance();
502 token.setName("query");
503 token.setTokenId("tokenID");
504
505 when(m_httpRecording.addRequest(m_connectionDetails,
506 "GET",
507 "/something?query=whatever"))
508 .thenReturn(request);
509
510 final String message = "GET /something?query=whatever HTTP/1.0\r\n\r\n";
511 final byte[] buffer = message.getBytes();
512 handler.handleRequest(buffer, buffer.length);
513
514 verify(m_httpRecording).addRequest(m_connectionDetails,
515 "GET",
516 "/something?query=whatever");
517 verifyNoMoreInteractions(m_httpRecording);
518 }
519
520 @Test public void testRequestBinaryBody() throws Exception {
521 final ConnectionHandler handler =
522 new ConnectionHandlerImplementation(
523 m_httpRecording, m_logger, m_regularExpressions,
524 m_uriParser, m_attributeStringParser, null,
525 m_commentSource, m_connectionDetails);
526
527 final RequestType request = RequestType.Factory.newInstance();
528 request.addNewHeaders();
529 request.setMethod(RequestType.Method.Enum.forString("POST"));
530
531 when(m_httpRecording.addRequest(m_connectionDetails,
532 "POST",
533 "/something"))
534 .thenReturn(request);
535
536
537 final String message =
538 "POST /something HTTP/1.0\r\n" +
539 "Content-Length: 150\r\n" +
540 "Content-Type: bah\r\n" +
541 "\r\n";
542
543 final byte[] buffer = message.getBytes();
544
545 final byte[] buffer2 = new byte[50];
546
547 for (int i = 0; i < buffer2.length; i++) {
548 buffer2[i] = (byte) i;
549 }
550
551
552
553 final byte[] buffer3 = new byte[buffer.length + buffer2.length + 100];
554 System.arraycopy(buffer, 0, buffer3, 0, buffer.length);
555 System.arraycopy(buffer2, 0, buffer3, buffer.length, buffer2.length);
556
557 handler.handleRequest(buffer3, buffer.length + buffer2.length);
558
559 handler.handleRequest(buffer2, 50);
560 handler.handleRequest(buffer2, 50);
561
562 handler.requestFinished();
563
564 assertEquals("bah", request.getBody().getContentType());
565 assertEquals(150, request.getBody().getBinary().length);
566 assertFalse(request.getBody().isSetEscapedString());
567 assertFalse(request.getBody().isSetFile());
568 assertFalse(request.getBody().isSetForm());
569 }
570
571 @Test public void testRequestFormBody() throws Exception {
572 final ConnectionHandler handler =
573 new ConnectionHandlerImplementation(
574 m_httpRecording, m_logger, m_regularExpressions,
575 m_uriParser, m_attributeStringParser, null,
576 m_commentSource, m_connectionDetails);
577
578 final RequestType request = RequestType.Factory.newInstance();
579 request.addNewHeaders();
580 request.setMethod(RequestType.Method.Enum.forString("POST"));
581
582 when(m_httpRecording.addRequest(m_connectionDetails,
583 "POST",
584 "/something"))
585 .thenReturn(request);
586
587 when(m_httpRecording.tokenReferenceExists(isA(String.class),
588 isA(String.class)))
589 .thenReturn(Boolean.FALSE);
590
591 final String message =
592 "POST /something HTTP/1.0\r\n" +
593 "Content-Type: application/x-www-form-urlencoded; blah\r\n" +
594 "\r\n" +
595 "red=5&blue=10";
596
597 final byte[] buffer = message.getBytes();
598 handler.handleRequest(buffer, buffer.length);
599
600 handler.requestFinished();
601
602 final FormFieldType[] formFieldArray =
603 request.getBody().getForm().getFormFieldArray();
604 assertEquals(2, formFieldArray.length);
605 assertEquals("red", formFieldArray[0].getName());
606 assertEquals("10", formFieldArray[1].getValue());
607 assertFalse(request.getBody().getForm().getMultipart());
608 assertFalse(request.getBody().isSetBinary());
609 assertFalse(request.getBody().isSetEscapedString());
610 assertFalse(request.getBody().isSetFile());
611 assertEquals(0, request.getBody().getForm().getTokenReferenceArray().length);
612
613 final RequestType request2 = RequestType.Factory.newInstance();
614 request2.addNewHeaders();
615 request2.setMethod(RequestType.Method.Enum.forString("POST"));
616
617 when(m_httpRecording.addRequest(m_connectionDetails,
618 "POST",
619 "/something"))
620 .thenReturn(request2);
621 when(m_httpRecording.tokenReferenceExists(isA(String.class),
622 isA(String.class)))
623 .thenReturn(Boolean.TRUE);
624
625 handler.handleRequest(buffer, buffer.length);
626
627 handler.requestFinished();
628
629 assertEquals(0, request2.getBody().getForm().getFormFieldArray().length);
630 assertFalse(request2.getBody().getForm().getMultipart());
631 assertFalse(request2.getBody().isSetBinary());
632 assertFalse(request2.getBody().isSetEscapedString());
633 assertFalse(request2.getBody().isSetFile());
634 final TokenReferenceType[] tokenReferenceArray =
635 request2.getBody().getForm().getTokenReferenceArray();
636 assertEquals(2, tokenReferenceArray.length);
637 assertFalse(tokenReferenceArray[0].isSetSource());
638 assertFalse(tokenReferenceArray[0].isSetNewValue());
639 }
640
641 @Test public void testRequestMultipartFormBody() throws Exception {
642 final ConnectionHandler handler =
643 new ConnectionHandlerImplementation(
644 m_httpRecording,
645 m_logger,
646 m_regularExpressions,
647 m_uriParser,
648 m_attributeStringParser, null,
649 m_commentSource,
650 m_connectionDetails);
651
652 final RequestType request = RequestType.Factory.newInstance();
653 request.addNewHeaders();
654 request.setMethod(RequestType.Method.Enum.forString("POST"));
655
656 when(m_httpRecording.addRequest(m_connectionDetails,
657 "POST",
658 "/something"))
659 .thenReturn(request);
660 when(m_httpRecording.tokenReferenceExists(isA(String.class),
661 isA(String.class)))
662 .thenReturn(Boolean.FALSE);
663
664
665 final String message =
666 "POST /something HTTP/1.0\r\n" +
667 "Content-Type: multipart/form-data; charset=UTF-8; boundary=---------------------------6549821653387387991112192755\r\n" +
668 "\r\n" +
669 "-----------------------------6549821653387387991112192755\r\n" +
670 "Content-Disposition: form-data; name=\"csrf_ticket\"\r\n" +
671 "\r\n" +
672 "XXXXXXXXXXXXXXXXXXXX\r\n" +
673 "-----------------------------6549821653387387991112192755\r\n" +
674 "Content-Disposition: form-data; name=\"title\"\r\n" +
675 "\r\n" +
676 "test\r\n" +
677 "-----------------------------6549821653387387991112192755\r\n" +
678 "Content-Disposition: form-data; name=\"enable_term\"\r\n" +
679 "\r\n" +
680 "0\r\n" +
681 "-----------------------------6549821653387387991112192755\r\n" +
682 "Content-Disposition: form-data; name=\"sterm_year\"\r\n" +
683 "\r\n" +
684 "2009\r\n" +
685 "-----------------------------6549821653387387991112192755\r\n" +
686 "Content-Disposition: form-data; name=\"sterm_month\"\r\n" +
687 "\r\n" +
688 "12\r\n" +
689 "-----------------------------6549821653387387991112192755\r\n" +
690 "Content-Disposition: form-data; name=\"sterm_day\"\r\n" +
691 "\r\n" +
692 "3\r\n" +
693 "-----------------------------6549821653387387991112192755\r\n" +
694 "Content-Disposition: form-data; name=\"sterm_hour\"\r\n" +
695 "\r\n" +
696 "\r\n" +
697 "-----------------------------6549821653387387991112192755\r\n" +
698 "Content-Disposition: form-data; name=\"sterm_minute\"\r\n" +
699 "\r\n" +
700 "\r\n" +
701 "-----------------------------6549821653387387991112192755\r\n" +
702 "Content-Disposition: form-data; name=\"eterm_year\"\r\n" +
703 "\r\n" +
704 "2009\r\n" +
705 "-----------------------------6549821653387387991112192755\r\n" +
706 "Content-Disposition: form-data; name=\"eterm_month\"\r\n" +
707 "\r\n" +
708 "12\r\n" +
709 "-----------------------------6549821653387387991112192755\r\n" +
710 "Content-Disposition: form-data; name=\"eterm_day\"\r\n" +
711 "\r\n" +
712 "3\r\n" +
713 "-----------------------------6549821653387387991112192755\r\n" +
714 "Content-Disposition: form-data; name=\"eterm_hour\"\r\n" +
715 "\r\n" +
716 "\r\n" +
717 "-----------------------------6549821653387387991112192755\r\n" +
718 "Content-Disposition: form-data; name=\"eterm_minute\"\r\n" +
719 "\r\n" +
720 "\r\n" +
721 "-----------------------------6549821653387387991112192755\r\n" +
722 "Content-Disposition: form-data; name=\"sterm_\"\r\n" +
723 "\r\n" +
724 "\r\n" +
725 "-----------------------------6549821653387387991112192755\r\n" +
726 "Content-Disposition: form-data; name=\"eterm_\"\r\n" +
727 "\r\n" +
728 "\r\n" +
729 "-----------------------------6549821653387387991112192755\r\n" +
730 "Content-Disposition: form-data; name=\"published\"\r\n" +
731 "\r\n" +
732 "\r\n" +
733 "-----------------------------6549821653387387991112192755\r\n" +
734 "Content-Disposition: form-data; name=\"editor\"\r\n" +
735 "\r\n" +
736 "0\r\n" +
737 "-----------------------------6549821653387387991112192755\r\n" +
738 "Content-Disposition: form-data; name=\"data\"\r\n" +
739 "\r\n" +
740 "testtesttesttesttesttesttesttesttesttesttest\r\n" +
741 "-----------------------------6549821653387387991112192755\r\n" +
742 "Content-Disposition: form-data; name=\"file0\"; filename=\"\"\r\n" +
743 "Content-Type: application/octet-stream\r\n" +
744 "\r\n" +
745 "\r\n" +
746 "-----------------------------6549821653387387991112192755\r\n" +
747 "Content-Disposition: form-data; name=\"can_follow\"\r\n" +
748 "\r\n" +
749 "1\r\n" +
750 "-----------------------------6549821653387387991112192755\r\n" +
751 "Content-Disposition: form-data; name=\"send\"\r\n" +
752 "\r\n" +
753 "AAA\r\n" +
754 "-----------------------------6549821653387387991112192755\r\n" +
755 "Content-Disposition: form-data; name=\"cid\"\r\n" +
756 "\r\n" +
757 "2\r\n" +
758 "-----------------------------6549821653387387991112192755\r\n" +
759 "Content-Disposition: form-data; name=\"aid\"\r\n" +
760 "\r\n" +
761 "\r\n" +
762 "-----------------------------6549821653387387991112192755--\r\n";
763
764 final byte[] buffer = message.getBytes("UTF-8");
765 handler.handleRequest(buffer, buffer.length);
766
767 handler.requestFinished();
768
769 final FormFieldType[] formFieldArray =
770 request.getBody().getForm().getFormFieldArray();
771 assertEquals(23, formFieldArray.length);
772 assertEquals("csrf_ticket", formFieldArray[0].getName());
773 assertEquals("XXXXXXXXXXXXXXXXXXXX", formFieldArray[0].getValue());
774 assertEquals("title", formFieldArray[1].getName());
775 assertEquals("test", formFieldArray[1].getValue());
776 assertEquals("enable_term", formFieldArray[2].getName());
777 assertEquals("0", formFieldArray[2].getValue());
778 assertEquals("sterm_year", formFieldArray[3].getName());
779 assertEquals("2009", formFieldArray[3].getValue());
780 assertEquals("sterm_month", formFieldArray[4].getName());
781 assertEquals("12", formFieldArray[4].getValue());
782 assertEquals("sterm_day", formFieldArray[5].getName());
783 assertEquals("3", formFieldArray[5].getValue());
784 assertEquals("sterm_hour", formFieldArray[6].getName());
785 assertEquals("", formFieldArray[6].getValue());
786 assertEquals("sterm_minute", formFieldArray[7].getName());
787 assertEquals("", formFieldArray[7].getValue());
788 assertEquals("eterm_year", formFieldArray[8].getName());
789 assertEquals("2009", formFieldArray[8].getValue());
790 assertEquals("eterm_month", formFieldArray[9].getName());
791 assertEquals("12", formFieldArray[9].getValue());
792 assertEquals("eterm_day", formFieldArray[10].getName());
793 assertEquals("3", formFieldArray[10].getValue());
794 assertEquals("eterm_hour", formFieldArray[11].getName());
795 assertEquals("", formFieldArray[11].getValue());
796 assertEquals("eterm_minute", formFieldArray[12].getName());
797 assertEquals("", formFieldArray[12].getValue());
798 assertEquals("sterm_", formFieldArray[13].getName());
799 assertEquals("", formFieldArray[13].getValue());
800 assertEquals("eterm_", formFieldArray[14].getName());
801 assertEquals("", formFieldArray[14].getValue());
802 assertEquals("published", formFieldArray[15].getName());
803 assertEquals("", formFieldArray[15].getValue());
804 assertEquals("editor", formFieldArray[16].getName());
805 assertEquals("0", formFieldArray[16].getValue());
806 assertEquals("data", formFieldArray[17].getName());
807 assertEquals("testtesttesttesttesttesttesttesttesttesttest", formFieldArray[17].getValue());
808 assertEquals("file0", formFieldArray[18].getName());
809 assertEquals("", formFieldArray[18].getValue());
810 assertEquals("can_follow", formFieldArray[19].getName());
811 assertEquals("1", formFieldArray[19].getValue());
812 assertEquals("send", formFieldArray[20].getName());
813 assertEquals("AAA", formFieldArray[20].getValue());
814 assertEquals("cid", formFieldArray[21].getName());
815 assertEquals("2", formFieldArray[21].getValue());
816 assertEquals("aid", formFieldArray[22].getName());
817 assertEquals("", formFieldArray[22].getValue());
818 assertEquals(23, formFieldArray.length);
819 assertTrue(request.getBody().getForm().getMultipart());
820 assertFalse(request.getBody().isSetBinary());
821 assertFalse(request.getBody().isSetEscapedString());
822 assertFalse(request.getBody().isSetFile());
823 assertEquals(0, request.getBody().getForm().getTokenReferenceArray().length);
824 }
825
826 @Test public void testRequestFileBody() throws Exception {
827 final ConnectionHandler handler =
828 new ConnectionHandlerImplementation(
829 m_httpRecording, m_logger, m_regularExpressions,
830 m_uriParser, m_attributeStringParser, null,
831 m_commentSource, m_connectionDetails);
832
833 final RequestType request = RequestType.Factory.newInstance();
834 request.addNewHeaders();
835 request.setMethod(RequestType.Method.Enum.forString("POST"));
836
837 final File file = new File(getDirectory(), "formData");
838
839
840 when(m_httpRecording.addRequest(m_connectionDetails,
841 "POST",
842 "/something"))
843 .thenReturn(request);
844
845 when(m_httpRecording.createBodyDataFileName()).thenReturn(file);
846
847 final String message =
848 "POST /something HTTP/1.0\r\n" +
849 "\r\n";
850
851 final byte[] buffer = message.getBytes();
852 handler.handleRequest(buffer, buffer.length);
853
854 final byte[] buffer2 = new byte[0x8000];
855
856 for (int i = 0; i < buffer2.length; i++) {
857 buffer2[i] = (byte) i;
858 }
859
860 handler.handleRequest(buffer2, buffer2.length);
861
862 handler.requestFinished();
863
864 assertEquals(file.getPath(), request.getBody().getFile());
865 assertTrue(file.exists());
866 assertTrue(file.canRead());
867 assertEquals(0x8000, file.length());
868 assertFalse(request.getBody().isSetBinary());
869 assertFalse(request.getBody().isSetForm());
870 assertFalse(request.getBody().isSetEscapedString());
871 }
872
873 @Test public void testRequestFileBody2() throws Exception {
874 final ConnectionHandler handler =
875 new ConnectionHandlerImplementation(
876 m_httpRecording, m_logger, m_regularExpressions,
877 m_uriParser, m_attributeStringParser, null,
878 m_commentSource, m_connectionDetails);
879
880 final RequestType request = RequestType.Factory.newInstance();
881 request.addNewHeaders();
882 request.setMethod(RequestType.Method.Enum.forString("POST"));
883
884 final File file = new File(getDirectory(), "formData");
885 file.createNewFile();
886 FileUtilities.setCanAccess(file, false);
887
888 when(m_httpRecording.addRequest(m_connectionDetails,
889 "POST",
890 "/something"))
891 .thenReturn(request);
892
893 when(m_httpRecording.createBodyDataFileName()).thenReturn(file);
894
895 final String message =
896 "POST /something HTTP/1.0\r\n" +
897 "\r\n";
898
899 final byte[] buffer = message.getBytes();
900 handler.handleRequest(buffer, buffer.length);
901
902 final byte[] buffer2 = new byte[0x8000];
903
904 for (int i = 0; i < buffer2.length; i++) {
905 buffer2[i] = (byte) i;
906 }
907
908 handler.handleRequest(buffer2, buffer2.length);
909
910 handler.requestFinished();
911
912 assertFalse(request.getBody().isSetFile());
913 assertFalse(request.getBody().isSetBinary());
914 assertFalse(request.getBody().isSetForm());
915 assertFalse(request.getBody().isSetEscapedString());
916
917 verify(m_logger).error(contains("Failed to write body"),
918 isA(FileNotFoundException.class));
919 }
920
921 @Test public void testPartitionedRequest() throws Exception {
922 final ConnectionHandler handler =
923 new ConnectionHandlerImplementation(
924 m_httpRecording, m_logger, m_regularExpressions,
925 m_uriParser, m_attributeStringParser, null,
926 m_commentSource, m_connectionDetails);
927
928 final byte[] message1Bytes = new String("G").getBytes("US-ASCII");
929 handler.handleRequest(message1Bytes, message1Bytes.length);
930
931 final byte[] message2Bytes =
932 new String("ET blah HTTP/1.1\n").getBytes("US-ASCII");
933
934 final RequestType request = RequestType.Factory.newInstance();
935 request.addNewHeaders();
936 request.setMethod(RequestType.Method.Enum.forString("GET"));
937
938 when(m_httpRecording.addRequest(m_connectionDetails,
939 "GET",
940 "blah"))
941 .thenReturn(request);
942
943 handler.handleRequest(message2Bytes, message2Bytes.length);
944
945 verify(m_httpRecording).addRequest(m_connectionDetails, "GET", "blah");
946 }
947
948 @Test public void testOverflowBuffer() {
949 final ConnectionHandler handler =
950 new ConnectionHandlerImplementation(
951 m_httpRecording, m_logger, m_regularExpressions,
952 m_uriParser, m_attributeStringParser, null,
953 m_commentSource, m_connectionDetails);
954
955 final byte[] buffer = new byte[0x10000];
956
957 for (int i = 0; i < buffer.length; i++) {
958 buffer[i] = (byte) i;
959 }
960
961 handler.handleRequest(buffer, buffer.length);
962
963 verify(m_logger).error(contains("Filled buffer without matching"),
964 isA(BufferOverflowException.class));
965
966
967 handler.handleRequest(buffer, 10);
968 }
969
970 @Test public void testWithBadResponseMessages() throws Exception {
971 final ConnectionHandler handler =
972 new ConnectionHandlerImplementation(
973 m_httpRecording, m_logger, m_regularExpressions,
974 m_uriParser, m_attributeStringParser, null,
975 m_commentSource, m_connectionDetails);
976
977
978 handler.handleResponse(new byte[0], 0);
979 verify(m_logger).error(contains("No current request"));
980
981 final RequestType request = RequestType.Factory.newInstance();
982 request.addNewHeaders();
983 request.setMethod(RequestType.Method.Enum.forString("GET"));
984
985 when(m_httpRecording.addRequest(m_connectionDetails,
986 "GET",
987 "/"))
988 .thenReturn(request);
989
990 final String message = "GET / HTTP/1.1\r\n";
991 final byte[] buffer = message.getBytes();
992 handler.handleRequest(buffer, buffer.length);
993
994
995
996 handler.handleResponse(new byte[0], 0);
997
998 verify(m_logger).error(contains("No current response"));
999 }
1000 }