001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: */
018:
019: package org.apache.jmeter.protocol.http.control;
020:
021: import java.io.ByteArrayOutputStream;
022: import java.io.InputStream;
023: import java.io.OutputStream;
024: import java.io.UnsupportedEncodingException;
025: import java.net.Socket; /*
026: import org.apache.jmeter.engine.util.ValueReplacer;
027: import org.apache.jmeter.protocol.http.control.HttpMirrorControl;
028: import org.apache.jmeter.protocol.http.sampler.HTTPSampler2;
029: import org.apache.jmeter.protocol.http.sampler.HTTPSamplerBase;
030: import org.apache.jmeter.protocol.http.util.EncoderCache;
031: import org.apache.jmeter.protocol.http.util.HTTPArgument;
032: import org.apache.jmeter.testelement.TestPlan;
033: import org.apache.jmeter.threads.JMeterContextService;
034: import org.apache.jmeter.threads.JMeterVariables;
035: import org.apache.jmeter.util.JMeterUtils;
036: import org.apache.oro.text.regex.MatchResult;
037: import org.apache.oro.text.regex.Pattern;
038: import org.apache.oro.text.regex.PatternMatcherInput;
039: import org.apache.oro.text.regex.Perl5Compiler;
040: import org.apache.oro.text.regex.Perl5Matcher;
041: */
042: import junit.framework.Test;
043: import junit.framework.TestCase;
044: import junit.framework.TestSuite;
045: import junit.extensions.TestSetup;
046:
047: /**
048: * Class for testing the HTTPMirrorThread, which is handling the
049: * incoming requests for the HTTPMirrorServer
050: */
051: public class TestHTTPMirrorThread extends TestCase {
052: /** The encodings used for http headers and control information */
053: private final static String ISO_8859_1 = "ISO-8859-1"; // $NON-NLS-1$
054: private final static String UTF_8 = "UTF-8"; // $NON-NLS-1$
055:
056: private static final byte[] CRLF = { 0x0d, 0x0a };
057: private final static int HTTP_SERVER_PORT = 8080;
058:
059: public TestHTTPMirrorThread(String arg0) {
060: super (arg0);
061: }
062:
063: public static Test suite() {
064: TestSetup setup = new TestSetup(new TestSuite(
065: TestHTTPMirrorThread.class)) {
066: private HttpMirrorServer httpServer;
067:
068: protected void setUp() throws Exception {
069: // Start the http server
070: httpServer = new HttpMirrorServer(HTTP_SERVER_PORT);
071: httpServer.start();
072: // Allow some time for the server to start
073: Thread.sleep(500);
074: }
075:
076: protected void tearDown() throws Exception {
077: // Shutdown the http server
078: httpServer.stopServer();
079: httpServer = null;
080: }
081: };
082: return setup;
083: };
084:
085: public void testGetRequest() throws Exception {
086: // Connect to the http server, and do a simple http get
087: Socket clientSocket = new Socket("localhost", HTTP_SERVER_PORT);
088: OutputStream outputStream = clientSocket.getOutputStream();
089: InputStream inputStream = clientSocket.getInputStream();
090:
091: // Write to the socket
092: ByteArrayOutputStream bos = new ByteArrayOutputStream();
093: // Headers
094: bos.write("GET / HTTP 1.1".getBytes(ISO_8859_1));
095: bos.write(CRLF);
096: bos.write("Host: localhost".getBytes(ISO_8859_1));
097: bos.write(CRLF);
098: bos.write(CRLF);
099: bos.close();
100: outputStream.write(bos.toByteArray());
101:
102: // Read the response
103: ByteArrayOutputStream response = new ByteArrayOutputStream();
104: byte[] buffer = new byte[1024];
105: int length = 0;
106: while ((length = inputStream.read(buffer)) != -1) {
107: response.write(buffer, 0, length);
108: }
109: response.close();
110: byte[] mirroredResponse = getMirroredResponse(response
111: .toByteArray());
112: // Check that the request and response matches
113: checkArraysHaveSameContent(bos.toByteArray(), mirroredResponse);
114: // Close the connection
115: clientSocket.close();
116:
117: // Connect to the http server, and do a simple http get, with
118: // a pause in the middle of transmitting the header
119: clientSocket = new Socket("localhost", HTTP_SERVER_PORT);
120: outputStream = clientSocket.getOutputStream();
121: inputStream = clientSocket.getInputStream();
122:
123: // Write to the socket
124: bos = new ByteArrayOutputStream();
125: // Headers
126: bos.write("GET / HTTP 1.1".getBytes(ISO_8859_1));
127: bos.write(CRLF);
128: // Write the start of the headers, and then sleep, so that the mirror
129: // thread will have to block to wait for more data to appear
130: bos.close();
131: byte[] firstChunk = bos.toByteArray();
132: outputStream.write(firstChunk);
133: Thread.sleep(300);
134: // Write the rest of the headers
135: bos = new ByteArrayOutputStream();
136: bos.write("Host: localhost".getBytes(ISO_8859_1));
137: bos.write(CRLF);
138: bos.write(CRLF);
139: bos.close();
140: byte[] secondChunk = bos.toByteArray();
141: outputStream.write(secondChunk);
142: // Read the response
143: response = new ByteArrayOutputStream();
144: buffer = new byte[1024];
145: length = 0;
146: while ((length = inputStream.read(buffer)) != -1) {
147: response.write(buffer, 0, length);
148: }
149: response.close();
150: mirroredResponse = getMirroredResponse(response.toByteArray());
151: // The content sent
152: bos = new ByteArrayOutputStream();
153: bos.write(firstChunk);
154: bos.write(secondChunk);
155: bos.close();
156: // Check that the request and response matches
157: checkArraysHaveSameContent(bos.toByteArray(), mirroredResponse);
158: // Close the connection
159: clientSocket.close();
160: }
161:
162: public void testPostRequest() throws Exception {
163: // Connect to the http server, and do a simple http post
164: Socket clientSocket = new Socket("localhost", HTTP_SERVER_PORT);
165: OutputStream outputStream = clientSocket.getOutputStream();
166: InputStream inputStream = clientSocket.getInputStream();
167: // Construct body
168: StringBuffer postBodyBuffer = new StringBuffer();
169: for (int i = 0; i < 1000; i++) {
170: postBodyBuffer.append("abc");
171: }
172: byte[] postBody = postBodyBuffer.toString()
173: .getBytes(ISO_8859_1);
174:
175: // Write to the socket
176: ByteArrayOutputStream bos = new ByteArrayOutputStream();
177: // Headers
178: bos.write("GET / HTTP 1.1".getBytes(ISO_8859_1));
179: bos.write(CRLF);
180: bos.write("Host: localhost".getBytes(ISO_8859_1));
181: bos.write(CRLF);
182: bos.write(("Content-type: text/plain; charset=" + ISO_8859_1)
183: .getBytes(ISO_8859_1));
184: bos.write(CRLF);
185: bos.write(("Content-length: " + postBody.length)
186: .getBytes(ISO_8859_1));
187: bos.write(CRLF);
188: bos.write(CRLF);
189: bos.write(postBody);
190: bos.close();
191: // Write the headers and body
192: outputStream.write(bos.toByteArray());
193: // Read the response
194: ByteArrayOutputStream response = new ByteArrayOutputStream();
195: byte[] buffer = new byte[1024];
196: int length = 0;
197: while ((length = inputStream.read(buffer)) != -1) {
198: response.write(buffer, 0, length);
199: }
200: response.close();
201: byte[] mirroredResponse = getMirroredResponse(response
202: .toByteArray());
203: // Check that the request and response matches
204: checkArraysHaveSameContent(bos.toByteArray(), mirroredResponse);
205: // Close the connection
206: clientSocket.close();
207:
208: // Connect to the http server, and do a simple http post, with
209: // a pause after transmitting the headers
210: clientSocket = new Socket("localhost", HTTP_SERVER_PORT);
211: outputStream = clientSocket.getOutputStream();
212: inputStream = clientSocket.getInputStream();
213:
214: // Write to the socket
215: bos = new ByteArrayOutputStream();
216: // Headers
217: bos.write("GET / HTTP 1.1".getBytes(ISO_8859_1));
218: bos.write(CRLF);
219: bos.write("Host: localhost".getBytes(ISO_8859_1));
220: bos.write(CRLF);
221: bos.write(("Content-type: text/plain; charset=" + ISO_8859_1)
222: .getBytes(ISO_8859_1));
223: bos.write(CRLF);
224: bos.write(("Content-length: " + postBody.length)
225: .getBytes(ISO_8859_1));
226: bos.write(CRLF);
227: bos.write(CRLF);
228: bos.close();
229: // Write the headers, and then sleep
230: bos.close();
231: byte[] firstChunk = bos.toByteArray();
232: outputStream.write(firstChunk);
233: Thread.sleep(300);
234:
235: // Write the body
236: byte[] secondChunk = postBody;
237: outputStream.write(secondChunk);
238: // Read the response
239: response = new ByteArrayOutputStream();
240: buffer = new byte[1024];
241: length = 0;
242: while ((length = inputStream.read(buffer)) != -1) {
243: response.write(buffer, 0, length);
244: }
245: response.close();
246: mirroredResponse = getMirroredResponse(response.toByteArray());
247: // The content sent
248: bos = new ByteArrayOutputStream();
249: bos.write(firstChunk);
250: bos.write(secondChunk);
251: bos.close();
252: // Check that the request and response matches
253: checkArraysHaveSameContent(bos.toByteArray(), mirroredResponse);
254: // Close the connection
255: clientSocket.close();
256:
257: // Connect to the http server, and do a simple http post with utf-8
258: // encoding of the body, which caused problems when reader/writer
259: // classes were used in the HttpMirrorThread
260: clientSocket = new Socket("localhost", HTTP_SERVER_PORT);
261: outputStream = clientSocket.getOutputStream();
262: inputStream = clientSocket.getInputStream();
263: // Construct body
264: postBodyBuffer = new StringBuffer();
265: for (int i = 0; i < 1000; i++) {
266: postBodyBuffer.append("\u0364\u00c5\u2052");
267: }
268: postBody = postBodyBuffer.toString().getBytes(UTF_8);
269:
270: // Write to the socket
271: bos = new ByteArrayOutputStream();
272: // Headers
273: bos.write("GET / HTTP 1.1".getBytes(ISO_8859_1));
274: bos.write(CRLF);
275: bos.write("Host: localhost".getBytes(ISO_8859_1));
276: bos.write(CRLF);
277: bos.write(("Content-type: text/plain; charset=" + UTF_8)
278: .getBytes(ISO_8859_1));
279: bos.write(CRLF);
280: bos.write(("Content-length: " + postBody.length)
281: .getBytes(ISO_8859_1));
282: bos.write(CRLF);
283: bos.write(CRLF);
284: bos.close();
285: // Write the headers, and then sleep
286: bos.close();
287: firstChunk = bos.toByteArray();
288: outputStream.write(firstChunk);
289: Thread.sleep(300);
290:
291: // Write the body
292: secondChunk = postBody;
293: outputStream.write(secondChunk);
294: // Read the response
295: response = new ByteArrayOutputStream();
296: buffer = new byte[1024];
297: length = 0;
298: while ((length = inputStream.read(buffer)) != -1) {
299: response.write(buffer, 0, length);
300: }
301: response.close();
302: mirroredResponse = getMirroredResponse(response.toByteArray());
303: // The content sent
304: bos = new ByteArrayOutputStream();
305: bos.write(firstChunk);
306: bos.write(secondChunk);
307: bos.close();
308: // Check that the request and response matches
309: checkArraysHaveSameContent(bos.toByteArray(), mirroredResponse);
310: // Close the connection
311: clientSocket.close();
312: }
313:
314: /*
315: public void testPostRequestChunked() throws Exception {
316: // TODO - implement testing of chunked post request
317: }
318: */
319:
320: /**
321: * Check that the the two byte arrays have identical content
322: *
323: * @param expected
324: * @param actual
325: * @throws UnsupportedEncodingException
326: */
327: private void checkArraysHaveSameContent(byte[] expected,
328: byte[] actual) throws UnsupportedEncodingException {
329: if (expected != null && actual != null) {
330: if (expected.length != actual.length) {
331: System.out
332: .println(">>>>>>>>>>>>>>>>>>>> (expected) : length "
333: + expected.length);
334: System.out.println(new String(expected, "UTF-8"));
335: System.out
336: .println("==================== (actual) : length "
337: + actual.length);
338: System.out.println(new String(actual, "UTF-8"));
339: System.out.println("<<<<<<<<<<<<<<<<<<<<");
340: fail("arrays have different length, expected is "
341: + expected.length + ", actual is "
342: + actual.length);
343: } else {
344: for (int i = 0; i < expected.length; i++) {
345: if (expected[i] != actual[i]) {
346: System.out
347: .println(">>>>>>>>>>>>>>>>>>>> (expected) : length "
348: + expected.length);
349: System.out.println(new String(expected, 0,
350: i + 1));
351: System.out
352: .println("==================== (actual) : length "
353: + actual.length);
354: System.out
355: .println(new String(actual, 0, i + 1));
356: System.out.println("<<<<<<<<<<<<<<<<<<<<");
357: /*
358: // Useful to when debugging
359: for(int j = 0; j < expected.length; j++) {
360: System.out.print(expected[j] + " ");
361: }
362: System.out.println();
363: for(int j = 0; j < actual.length; j++) {
364: System.out.print(actual[j] + " ");
365: }
366: System.out.println();
367: */
368: fail("byte at position " + i
369: + " is different, expected is "
370: + expected[i] + ", actual is "
371: + actual[i]);
372: }
373: }
374: }
375: } else {
376: fail("expected or actual byte arrays were null");
377: }
378: }
379:
380: private byte[] getMirroredResponse(byte[] allResponse) {
381: // The response includes the headers from the mirror server,
382: // we want to skip those, to only keep the content mirrored.
383: // Look for the first CRLFCRLF section
384: int startOfMirrorResponse = 0;
385: for (int i = 0; i < allResponse.length; i++) {
386: // TODO : This is a bit fragile
387: if (allResponse[i] == 0x0d && allResponse[i + 1] == 0x0a
388: && allResponse[i + 2] == 0x0d
389: && allResponse[i + 3] == 0x0a) {
390: startOfMirrorResponse = i + 4;
391: break;
392: }
393: }
394: byte[] mirrorResponse = new byte[allResponse.length
395: - startOfMirrorResponse];
396: System.arraycopy(allResponse, startOfMirrorResponse,
397: mirrorResponse, 0, mirrorResponse.length);
398: return mirrorResponse;
399: }
400: }
|