0001: /*
0002: * Licensed to the Apache Software Foundation (ASF) under one or more
0003: * contributor license agreements. See the NOTICE file distributed with
0004: * this work for additional information regarding copyright ownership.
0005: * The ASF licenses this file to You under the Apache License, Version 2.0
0006: * (the "License"); you may not use this file except in compliance with
0007: * the License. You may obtain a copy of the License at
0008: *
0009: * http://www.apache.org/licenses/LICENSE-2.0
0010: *
0011: * Unless required by applicable law or agreed to in writing, software
0012: * distributed under the License is distributed on an "AS IS" BASIS,
0013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014: * See the License for the specific language governing permissions and
0015: * limitations under the License.
0016: *
0017: */
0018:
0019: package org.apache.jmeter.protocol.http.sampler;
0020:
0021: import java.io.ByteArrayOutputStream;
0022: import java.io.File;
0023: import java.io.FileOutputStream;
0024: import java.io.IOException;
0025: import java.io.OutputStream;
0026: import java.io.UnsupportedEncodingException;
0027: import java.net.HttpURLConnection;
0028: import java.net.MalformedURLException;
0029: import java.net.URL;
0030: import java.net.URLDecoder;
0031: import java.net.URLEncoder;
0032: import java.util.HashMap;
0033: import java.util.Map;
0034:
0035: import junit.framework.TestCase;
0036:
0037: import org.apache.jmeter.config.Arguments;
0038: import org.apache.jmeter.protocol.http.util.HTTPArgument;
0039: import org.apache.jorphan.logging.LoggingManager;
0040: import org.apache.log.Logger;
0041:
0042: public class PostWriterTest extends TestCase {
0043:
0044: private static final Logger log = LoggingManager
0045: .getLoggerForClass();
0046:
0047: private static final String UTF_8 = "UTF-8";
0048: private final static String HTTP_ENCODING = "ISO-8859-1";
0049: private final static byte[] CRLF = { 0x0d, 0x0A };
0050: private static byte[] TEST_FILE_CONTENT;
0051:
0052: private StubURLConnection connection;
0053: private HTTPSampler sampler;
0054: private File temporaryFile;
0055:
0056: PostWriter postWriter;
0057:
0058: protected void setUp() throws Exception {
0059: establishConnection();
0060: sampler = new HTTPSampler();// This must be the original (Java) HTTP sampler
0061: postWriter = new PostWriter();
0062:
0063: // Create the test file content
0064: TEST_FILE_CONTENT = "foo content &?=01234+56789-\u007c\u2aa1\u266a\u0153\u20a1\u0115\u0364\u00c5\u2052"
0065: .getBytes(UTF_8);
0066:
0067: // create a temporary file to make sure we always have a file to give to the PostWriter
0068: // Whereever we are or Whatever the current path is.
0069: temporaryFile = File.createTempFile("foo", "txt");
0070: OutputStream output = new FileOutputStream(temporaryFile);
0071: output.write(TEST_FILE_CONTENT);
0072: output.flush();
0073: output.close();
0074: }
0075:
0076: protected void tearDown() throws Exception {
0077: // delete temporay file
0078: temporaryFile.delete();
0079: }
0080:
0081: /*
0082: * Test method for 'org.apache.jmeter.protocol.http.sampler.postWriter.sendPostData(URLConnection, HTTPSampler)'
0083: * This method test sending a request which contains both formdata and file content
0084: */
0085: public void testSendPostData() throws IOException {
0086: sampler.setMethod(HTTPSamplerBase.POST);
0087: setupFilepart(sampler);
0088: String titleValue = "mytitle";
0089: String descriptionValue = "mydescription";
0090: setupFormData(sampler, titleValue, descriptionValue);
0091:
0092: // Test sending data with default encoding
0093: String contentEncoding = "";
0094: sampler.setContentEncoding(contentEncoding);
0095: postWriter.setHeaders(connection, sampler);
0096: postWriter.sendPostData(connection, sampler);
0097:
0098: checkContentTypeMultipart(connection, PostWriter.BOUNDARY);
0099: byte[] expectedFormBody = createExpectedOutput(
0100: PostWriter.BOUNDARY, null, titleValue,
0101: descriptionValue, TEST_FILE_CONTENT);
0102: checkContentLength(connection, expectedFormBody.length);
0103: checkArraysHaveSameContent(expectedFormBody, connection
0104: .getOutputStreamContent());
0105: connection.disconnect();
0106:
0107: // Test sending data as ISO-8859-1
0108: establishConnection();
0109: contentEncoding = "ISO-8859-1";
0110: sampler.setContentEncoding(contentEncoding);
0111: postWriter.setHeaders(connection, sampler);
0112: postWriter.sendPostData(connection, sampler);
0113:
0114: checkContentTypeMultipart(connection, PostWriter.BOUNDARY);
0115: expectedFormBody = createExpectedOutput(PostWriter.BOUNDARY,
0116: contentEncoding, titleValue, descriptionValue,
0117: TEST_FILE_CONTENT);
0118: checkContentLength(connection, expectedFormBody.length);
0119: checkArraysHaveSameContent(expectedFormBody, connection
0120: .getOutputStreamContent());
0121: connection.disconnect();
0122:
0123: // Test sending data as UTF-8
0124: establishConnection();
0125: titleValue = "mytitle\u0153\u20a1\u0115\u00c5";
0126: descriptionValue = "mydescription\u0153\u20a1\u0115\u00c5";
0127: contentEncoding = UTF_8;
0128: sampler.setContentEncoding(contentEncoding);
0129: setupFormData(sampler, titleValue, descriptionValue);
0130: postWriter.setHeaders(connection, sampler);
0131: postWriter.sendPostData(connection, sampler);
0132: checkContentTypeMultipart(connection, PostWriter.BOUNDARY);
0133: expectedFormBody = createExpectedOutput(PostWriter.BOUNDARY,
0134: contentEncoding, titleValue, descriptionValue,
0135: TEST_FILE_CONTENT);
0136: checkContentLength(connection, expectedFormBody.length);
0137: checkArraysHaveSameContent(expectedFormBody, connection
0138: .getOutputStreamContent());
0139: connection.disconnect();
0140:
0141: // Test sending UTF-8 data with ISO-8859-1 content encoding
0142: establishConnection();
0143: contentEncoding = UTF_8;
0144: sampler.setContentEncoding("ISO-8859-1");
0145: postWriter.setHeaders(connection, sampler);
0146: postWriter.sendPostData(connection, sampler);
0147: checkContentTypeMultipart(connection, PostWriter.BOUNDARY);
0148: expectedFormBody = createExpectedOutput(PostWriter.BOUNDARY,
0149: contentEncoding, titleValue, descriptionValue,
0150: TEST_FILE_CONTENT);
0151: checkContentLength(connection, expectedFormBody.length);
0152: checkArraysHaveDifferentContent(expectedFormBody, connection
0153: .getOutputStreamContent());
0154: connection.disconnect();
0155: }
0156:
0157: /*
0158: * Test method for 'org.apache.jmeter.protocol.http.sampler.postWriter.sendPostData(URLConnection, HTTPSampler)'
0159: * This method test sending a HTTPSampler with form parameters, and only
0160: * the filename of a file.
0161: */
0162: public void testSendPostData_NoFilename() throws IOException {
0163: setupNoFilename(sampler);
0164: String titleValue = "mytitle";
0165: String descriptionValue = "mydescription";
0166: setupFormData(sampler, titleValue, descriptionValue);
0167:
0168: // Test sending data with default encoding
0169: String contentEncoding = "";
0170: sampler.setContentEncoding(contentEncoding);
0171: postWriter.setHeaders(connection, sampler);
0172: postWriter.sendPostData(connection, sampler);
0173:
0174: checkContentTypeUrlEncoded(connection);
0175: byte[] expectedUrl = "title=mytitle&description=mydescription"
0176: .getBytes();
0177: checkContentLength(connection, expectedUrl.length);
0178: checkArraysHaveSameContent(expectedUrl, connection
0179: .getOutputStreamContent());
0180: expectedUrl = "title=mytitle&description=mydescription"
0181: .getBytes(UTF_8);
0182: checkContentLength(connection, expectedUrl.length);
0183: checkArraysHaveSameContent(expectedUrl, connection
0184: .getOutputStreamContent());
0185: connection.disconnect();
0186:
0187: // Test sending data as ISO-8859-1
0188: establishConnection();
0189: contentEncoding = "ISO-8859-1";
0190: sampler.setContentEncoding(contentEncoding);
0191: postWriter.setHeaders(connection, sampler);
0192: postWriter.sendPostData(connection, sampler);
0193:
0194: checkContentTypeUrlEncoded(connection);
0195: expectedUrl = "title=mytitle&description=mydescription"
0196: .getBytes(contentEncoding);
0197: checkContentLength(connection, expectedUrl.length);
0198: checkArraysHaveSameContent(expectedUrl, connection
0199: .getOutputStreamContent());
0200: expectedUrl = "title=mytitle&description=mydescription"
0201: .getBytes(UTF_8);
0202: checkContentLength(connection, expectedUrl.length);
0203: checkArraysHaveSameContent(expectedUrl, connection
0204: .getOutputStreamContent());
0205: connection.disconnect();
0206: }
0207:
0208: /*
0209: * Test method for 'org.apache.jmeter.protocol.http.sampler.postWriter.sendPostData(URLConnection, HTTPSampler)'
0210: * This method test sending file content as the only content of the post body
0211: */
0212: public void testSendPostData_FileAsBody() throws IOException {
0213: setupFilepart(sampler, "", temporaryFile, "");
0214:
0215: // Check using default encoding
0216: postWriter.setHeaders(connection, sampler);
0217: postWriter.sendPostData(connection, sampler);
0218:
0219: checkContentLength(connection, TEST_FILE_CONTENT.length);
0220: checkArraysHaveSameContent(TEST_FILE_CONTENT, connection
0221: .getOutputStreamContent());
0222: connection.disconnect();
0223:
0224: // Check using a different encoding
0225:
0226: String otherEncoding;
0227: final String fileEncoding = System.getProperty("file.encoding");// $NON-NLS-1$
0228: log.info("file.encoding: " + fileEncoding);
0229: if (UTF_8.equalsIgnoreCase(fileEncoding)
0230: || "UTF8".equalsIgnoreCase(fileEncoding)) {// $NON-NLS-1$
0231: otherEncoding = "ISO-8859-1"; // $NON-NLS-1$
0232: } else {
0233: otherEncoding = UTF_8;
0234: }
0235: log.info("Using other encoding: " + otherEncoding);
0236: establishConnection();
0237: sampler.setContentEncoding(otherEncoding);
0238: // File content is sent as binary, so the content encoding should not change the file data
0239: postWriter.setHeaders(connection, sampler);
0240: postWriter.sendPostData(connection, sampler);
0241:
0242: checkContentLength(connection, TEST_FILE_CONTENT.length);
0243: checkArraysHaveSameContent(TEST_FILE_CONTENT, connection
0244: .getOutputStreamContent());
0245: // Check that other encoding is not the current encoding
0246: checkArraysHaveDifferentContent(new String(TEST_FILE_CONTENT)
0247: .getBytes(otherEncoding), connection
0248: .getOutputStreamContent());
0249:
0250: // If we have both file as body, and form data, then only form data will be sent
0251: setupFormData(sampler);
0252: establishConnection();
0253: sampler.setContentEncoding("");
0254: postWriter.setHeaders(connection, sampler);
0255: postWriter.sendPostData(connection, sampler);
0256:
0257: checkContentTypeUrlEncoded(connection);
0258: byte[] expectedUrl = "title=mytitle&description=mydescription"
0259: .getBytes();
0260: checkContentLength(connection, expectedUrl.length);
0261: checkArraysHaveSameContent(expectedUrl, connection
0262: .getOutputStreamContent());
0263: }
0264:
0265: /*
0266: * Test method for 'org.apache.jmeter.protocol.http.sampler.postWriter.sendPostData(URLConnection, HTTPSampler)'
0267: * This method test sending only a file multipart.
0268: */
0269: public void testSendFileData_Multipart() throws IOException {
0270: sampler.setMethod(HTTPSamplerBase.POST);
0271: String fileField = "upload";
0272: String mimeType = "text/plain";
0273: File file = temporaryFile;
0274: byte[] fileContent = TEST_FILE_CONTENT;
0275: setupFilepart(sampler, fileField, file, mimeType);
0276:
0277: // Test sending data with default encoding
0278: String contentEncoding = "";
0279: sampler.setContentEncoding(contentEncoding);
0280: postWriter.setHeaders(connection, sampler);
0281: postWriter.sendPostData(connection, sampler);
0282:
0283: checkContentTypeMultipart(connection, PostWriter.BOUNDARY);
0284: byte[] expectedFormBody = createExpectedFilepartOutput(
0285: PostWriter.BOUNDARY, fileField, file, mimeType,
0286: fileContent, true, true);
0287: checkContentLength(connection, expectedFormBody.length);
0288: checkArraysHaveSameContent(expectedFormBody, connection
0289: .getOutputStreamContent());
0290: connection.disconnect();
0291:
0292: // Test sending data as ISO-8859-1
0293: establishConnection();
0294: contentEncoding = "ISO-8859-1";
0295: sampler.setContentEncoding(contentEncoding);
0296: postWriter.setHeaders(connection, sampler);
0297: postWriter.sendPostData(connection, sampler);
0298:
0299: checkContentTypeMultipart(connection, PostWriter.BOUNDARY);
0300: expectedFormBody = createExpectedFilepartOutput(
0301: PostWriter.BOUNDARY, fileField, file, mimeType,
0302: fileContent, true, true);
0303: checkContentLength(connection, expectedFormBody.length);
0304: checkArraysHaveSameContent(expectedFormBody, connection
0305: .getOutputStreamContent());
0306: connection.disconnect();
0307:
0308: // Test sending data as UTF-8
0309: establishConnection();
0310: fileField = "some_file_field";
0311: mimeType = "image/png";
0312: contentEncoding = UTF_8;
0313: sampler.setContentEncoding(contentEncoding);
0314: setupFilepart(sampler, fileField, file, mimeType);
0315: postWriter.setHeaders(connection, sampler);
0316: postWriter.sendPostData(connection, sampler);
0317:
0318: checkContentTypeMultipart(connection, PostWriter.BOUNDARY);
0319: expectedFormBody = createExpectedFilepartOutput(
0320: PostWriter.BOUNDARY, fileField, file, mimeType,
0321: fileContent, true, true);
0322: checkContentLength(connection, expectedFormBody.length);
0323: checkArraysHaveSameContent(expectedFormBody, connection
0324: .getOutputStreamContent());
0325: connection.disconnect();
0326: }
0327:
0328: /*
0329: * Test method for 'org.apache.jmeter.protocol.http.sampler.postWriter.sendPostData(URLConnection, HTTPSampler)'
0330: * This method test sending only a formdata, as a multipart/form-data request.
0331: */
0332: public void testSendFormData_Multipart() throws IOException {
0333: sampler.setMethod(HTTPSamplerBase.POST);
0334: String titleField = "title";
0335: String titleValue = "mytitle";
0336: String descriptionField = "description";
0337: String descriptionValue = "mydescription";
0338: setupFormData(sampler, titleValue, descriptionValue);
0339: // Tell sampler to do multipart, even if we have no files to upload
0340: sampler.setDoMultipartPost(true);
0341:
0342: // Test sending data with default encoding
0343: String contentEncoding = "";
0344: sampler.setContentEncoding(contentEncoding);
0345: postWriter.setHeaders(connection, sampler);
0346: postWriter.sendPostData(connection, sampler);
0347:
0348: checkContentTypeMultipart(connection, PostWriter.BOUNDARY);
0349: byte[] expectedFormBody = createExpectedFormdataOutput(
0350: PostWriter.BOUNDARY, null, titleField, titleValue,
0351: descriptionField, descriptionValue, true, true);
0352: checkContentLength(connection, expectedFormBody.length);
0353: checkArraysHaveSameContent(expectedFormBody, connection
0354: .getOutputStreamContent());
0355: connection.disconnect();
0356:
0357: // Test sending data as ISO-8859-1
0358: establishConnection();
0359: contentEncoding = "ISO-8859-1";
0360: sampler.setContentEncoding(contentEncoding);
0361: postWriter.setHeaders(connection, sampler);
0362: postWriter.sendPostData(connection, sampler);
0363:
0364: checkContentTypeMultipart(connection, PostWriter.BOUNDARY);
0365: expectedFormBody = createExpectedFormdataOutput(
0366: PostWriter.BOUNDARY, contentEncoding, titleField,
0367: titleValue, descriptionField, descriptionValue, true,
0368: true);
0369: checkContentLength(connection, expectedFormBody.length);
0370: checkArraysHaveSameContent(expectedFormBody, connection
0371: .getOutputStreamContent());
0372: connection.disconnect();
0373:
0374: // Test sending data as ISO-8859-1, with values that need to be urlencoded
0375: establishConnection();
0376: titleValue = "mytitle+123 456&yes";
0377: descriptionValue = "mydescription and some spaces";
0378: contentEncoding = "ISO-8859-1";
0379: sampler.setContentEncoding(contentEncoding);
0380: setupFormData(sampler, titleValue, descriptionValue);
0381: postWriter.setHeaders(connection, sampler);
0382: postWriter.sendPostData(connection, sampler);
0383:
0384: checkContentTypeMultipart(connection, PostWriter.BOUNDARY);
0385: expectedFormBody = createExpectedFormdataOutput(
0386: PostWriter.BOUNDARY, contentEncoding, titleField,
0387: titleValue, descriptionField, descriptionValue, true,
0388: true);
0389: checkContentLength(connection, expectedFormBody.length);
0390: checkArraysHaveSameContent(expectedFormBody, connection
0391: .getOutputStreamContent());
0392: connection.disconnect();
0393:
0394: // Test sending data as UTF-8
0395: establishConnection();
0396: titleValue = "mytitle\u0153\u20a1\u0115\u00c5";
0397: descriptionValue = "mydescription\u0153\u20a1\u0115\u00c5";
0398: contentEncoding = UTF_8;
0399: sampler.setContentEncoding(contentEncoding);
0400: setupFormData(sampler, titleValue, descriptionValue);
0401: postWriter.setHeaders(connection, sampler);
0402: postWriter.sendPostData(connection, sampler);
0403:
0404: checkContentTypeMultipart(connection, PostWriter.BOUNDARY);
0405: expectedFormBody = createExpectedFormdataOutput(
0406: PostWriter.BOUNDARY, contentEncoding, titleField,
0407: titleValue, descriptionField, descriptionValue, true,
0408: true);
0409: checkContentLength(connection, expectedFormBody.length);
0410: checkArraysHaveSameContent(expectedFormBody, connection
0411: .getOutputStreamContent());
0412: connection.disconnect();
0413:
0414: // Test sending data as UTF-8, with values that would have been urlencoded
0415: // if it was not sent as multipart
0416: establishConnection();
0417: titleValue = "mytitle\u0153+\u20a1 \u0115&yes\u00c5";
0418: descriptionValue = "mydescription \u0153 \u20a1 \u0115 \u00c5";
0419: contentEncoding = UTF_8;
0420: sampler.setContentEncoding(contentEncoding);
0421: setupFormData(sampler, titleValue, descriptionValue);
0422: postWriter.setHeaders(connection, sampler);
0423: postWriter.sendPostData(connection, sampler);
0424:
0425: checkContentTypeMultipart(connection, PostWriter.BOUNDARY);
0426: expectedFormBody = createExpectedFormdataOutput(
0427: PostWriter.BOUNDARY, contentEncoding, titleField,
0428: titleValue, descriptionField, descriptionValue, true,
0429: true);
0430: checkContentLength(connection, expectedFormBody.length);
0431: checkArraysHaveSameContent(expectedFormBody, connection
0432: .getOutputStreamContent());
0433: connection.disconnect();
0434: }
0435:
0436: /*
0437: * Test method for 'org.apache.jmeter.protocol.http.sampler.postWriter.sendPostData(URLConnection, HTTPSampler)'
0438: * This method test sending only a formdata, as urlencoded data
0439: */
0440: public void testSendFormData_Urlencoded() throws IOException {
0441: String titleValue = "mytitle";
0442: String descriptionValue = "mydescription";
0443: setupFormData(sampler, titleValue, descriptionValue);
0444:
0445: // Test sending data with default encoding
0446: String contentEncoding = "";
0447: sampler.setContentEncoding(contentEncoding);
0448: postWriter.setHeaders(connection, sampler);
0449: postWriter.sendPostData(connection, sampler);
0450:
0451: checkContentTypeUrlEncoded(connection);
0452: byte[] expectedUrl = ("title=" + titleValue + "&description=" + descriptionValue)
0453: .getBytes("US-ASCII");
0454: checkContentLength(connection, expectedUrl.length);
0455: checkArraysHaveSameContent(expectedUrl, connection
0456: .getOutputStreamContent());
0457: assertEquals(URLDecoder.decode(new String(expectedUrl,
0458: "US-ASCII"), "ISO-8859-1"), URLDecoder.decode(
0459: new String(connection.getOutputStreamContent(),
0460: "US-ASCII"), "ISO-8859-1"));
0461: connection.disconnect();
0462:
0463: // Test sending data as ISO-8859-1
0464: establishConnection();
0465: contentEncoding = "ISO-8859-1";
0466: sampler.setContentEncoding(contentEncoding);
0467: postWriter.setHeaders(connection, sampler);
0468: postWriter.sendPostData(connection, sampler);
0469:
0470: checkContentTypeUrlEncoded(connection);
0471: expectedUrl = new String("title=" + titleValue
0472: + "&description=" + descriptionValue)
0473: .getBytes("US-ASCII");
0474: checkContentLength(connection, expectedUrl.length);
0475: checkArraysHaveSameContent(expectedUrl, connection
0476: .getOutputStreamContent());
0477: assertEquals(URLDecoder.decode(new String(expectedUrl,
0478: "US-ASCII"), contentEncoding), URLDecoder.decode(
0479: new String(connection.getOutputStreamContent(),
0480: "US-ASCII"), contentEncoding));
0481: connection.disconnect();
0482:
0483: // Test sending data as ISO-8859-1, with values that need to be urlencoded
0484: establishConnection();
0485: titleValue = "mytitle+123 456&yes";
0486: descriptionValue = "mydescription and some spaces";
0487: contentEncoding = "ISO-8859-1";
0488: sampler.setContentEncoding(contentEncoding);
0489: setupFormData(sampler, titleValue, descriptionValue);
0490: postWriter.setHeaders(connection, sampler);
0491: postWriter.sendPostData(connection, sampler);
0492:
0493: checkContentTypeUrlEncoded(connection);
0494: String expectedString = "title="
0495: + URLEncoder.encode(titleValue, contentEncoding)
0496: + "&description="
0497: + URLEncoder.encode(descriptionValue, contentEncoding);
0498: expectedUrl = expectedString.getBytes(contentEncoding);
0499: checkContentLength(connection, expectedUrl.length);
0500: checkArraysHaveSameContent(expectedUrl, connection
0501: .getOutputStreamContent());
0502: assertEquals(URLDecoder.decode(new String(expectedUrl,
0503: "US-ASCII"), contentEncoding), URLDecoder.decode(
0504: new String(connection.getOutputStreamContent(),
0505: "US-ASCII"), contentEncoding));
0506: String unencodedString = "title=" + titleValue
0507: + "&description=" + descriptionValue;
0508: byte[] unexpectedUrl = unencodedString.getBytes(UTF_8);
0509: checkArraysHaveDifferentContent(unexpectedUrl, connection
0510: .getOutputStreamContent());
0511: connection.disconnect();
0512:
0513: // Test sending data as UTF-8
0514: establishConnection();
0515: titleValue = "mytitle\u0153\u20a1\u0115\u00c5";
0516: descriptionValue = "mydescription\u0153\u20a1\u0115\u00c5";
0517: contentEncoding = UTF_8;
0518: sampler.setContentEncoding(contentEncoding);
0519: setupFormData(sampler, titleValue, descriptionValue);
0520: postWriter.setHeaders(connection, sampler);
0521: postWriter.sendPostData(connection, sampler);
0522:
0523: checkContentTypeUrlEncoded(connection);
0524: expectedString = "title="
0525: + URLEncoder.encode(titleValue, contentEncoding)
0526: + "&description="
0527: + URLEncoder.encode(descriptionValue, contentEncoding);
0528: expectedUrl = expectedString.getBytes("US-ASCII");
0529: checkContentLength(connection, expectedUrl.length);
0530: checkArraysHaveSameContent(expectedUrl, connection
0531: .getOutputStreamContent());
0532: assertEquals(URLDecoder.decode(new String(expectedUrl,
0533: "US-ASCII"), contentEncoding), URLDecoder.decode(
0534: new String(connection.getOutputStreamContent(),
0535: "US-ASCII"), contentEncoding));
0536: connection.disconnect();
0537:
0538: // Test sending data as UTF-8, with values that needs to be urlencoded
0539: establishConnection();
0540: titleValue = "mytitle\u0153+\u20a1 \u0115&yes\u00c5";
0541: descriptionValue = "mydescription \u0153 \u20a1 \u0115 \u00c5";
0542: contentEncoding = UTF_8;
0543: sampler.setContentEncoding(contentEncoding);
0544: setupFormData(sampler, titleValue, descriptionValue);
0545: postWriter.setHeaders(connection, sampler);
0546: postWriter.sendPostData(connection, sampler);
0547:
0548: checkContentTypeUrlEncoded(connection);
0549: expectedString = "title="
0550: + URLEncoder.encode(titleValue, UTF_8)
0551: + "&description="
0552: + URLEncoder.encode(descriptionValue, UTF_8);
0553: expectedUrl = expectedString.getBytes("US-ASCII");
0554: checkContentLength(connection, expectedUrl.length);
0555: checkArraysHaveSameContent(expectedUrl, connection
0556: .getOutputStreamContent());
0557: assertEquals(URLDecoder.decode(new String(expectedUrl,
0558: "US-ASCII"), contentEncoding), URLDecoder.decode(
0559: new String(connection.getOutputStreamContent(),
0560: "US-ASCII"), contentEncoding));
0561: unencodedString = "title=" + titleValue + "&description="
0562: + descriptionValue;
0563: unexpectedUrl = unencodedString.getBytes("US-ASCII");
0564: checkArraysHaveDifferentContent(unexpectedUrl, connection
0565: .getOutputStreamContent());
0566: connection.disconnect();
0567:
0568: // Test sending parameters which are urlencoded beforehand
0569: // The values must be URL encoded with UTF-8 encoding, because that
0570: // is what the HTTPArgument assumes
0571: // %C3%85 in UTF-8 is the same as %C5 in ISO-8859-1, which is the same as Å
0572: titleValue = "mytitle%20and%20space%2Ftest%C3%85";
0573: descriptionValue = "mydescription+and+plus+as+space%2Ftest%C3%85";
0574: setupFormData(sampler, true, titleValue, descriptionValue);
0575:
0576: // Test sending data with default encoding
0577: establishConnection();
0578: contentEncoding = "";
0579: sampler.setContentEncoding(contentEncoding);
0580: postWriter.setHeaders(connection, sampler);
0581: postWriter.sendPostData(connection, sampler);
0582:
0583: checkContentTypeUrlEncoded(connection);
0584: expectedUrl = new String("title="
0585: + titleValue.replaceAll("%20", "+").replaceAll(
0586: "%C3%85", "%C5") + "&description="
0587: + descriptionValue.replaceAll("%C3%85", "%C5"))
0588: .getBytes("US-ASCII");
0589: checkContentLength(connection, expectedUrl.length);
0590: checkArraysHaveSameContent(expectedUrl, connection
0591: .getOutputStreamContent());
0592: assertEquals(URLDecoder.decode(new String(expectedUrl,
0593: "US-ASCII"), "ISO-8859-1"), // HTTPSampler uses ISO-8859-1 as default encoding
0594: URLDecoder.decode(new String(connection
0595: .getOutputStreamContent(), "US-ASCII"),
0596: "ISO-8859-1")); // HTTPSampler uses ISO-8859-1 as default encoding
0597: connection.disconnect();
0598:
0599: // Test sending data as ISO-8859-1
0600: establishConnection();
0601: contentEncoding = "ISO-8859-1";
0602: sampler.setContentEncoding(contentEncoding);
0603: postWriter.setHeaders(connection, sampler);
0604: postWriter.sendPostData(connection, sampler);
0605:
0606: checkContentTypeUrlEncoded(connection);
0607: expectedUrl = new String("title="
0608: + titleValue.replaceAll("%20", "+").replaceAll(
0609: "%C3%85", "%C5") + "&description="
0610: + descriptionValue.replaceAll("%C3%85", "%C5"))
0611: .getBytes("US-ASCII");
0612: checkContentLength(connection, expectedUrl.length);
0613: checkArraysHaveSameContent(expectedUrl, connection
0614: .getOutputStreamContent());
0615: assertEquals(URLDecoder.decode(new String(expectedUrl,
0616: "US-ASCII"), contentEncoding), URLDecoder.decode(
0617: new String(connection.getOutputStreamContent(),
0618: "US-ASCII"), contentEncoding));
0619: connection.disconnect();
0620:
0621: // Test sending data as UTF-8
0622: establishConnection();
0623: contentEncoding = UTF_8;
0624: sampler.setContentEncoding(contentEncoding);
0625: postWriter.setHeaders(connection, sampler);
0626: postWriter.sendPostData(connection, sampler);
0627:
0628: checkContentTypeUrlEncoded(connection);
0629: expectedUrl = new String("title="
0630: + titleValue.replaceAll("%20", "+") + "&description="
0631: + descriptionValue).getBytes("US-ASCII");
0632: checkContentLength(connection, expectedUrl.length);
0633: checkArraysHaveSameContent(expectedUrl, connection
0634: .getOutputStreamContent());
0635: assertEquals(URLDecoder.decode(new String(expectedUrl,
0636: "US-ASCII"), contentEncoding), URLDecoder.decode(
0637: new String(connection.getOutputStreamContent(),
0638: "US-ASCII"), contentEncoding));
0639: connection.disconnect();
0640: }
0641:
0642: /*
0643: * Test method for 'org.apache.jmeter.protocol.http.sampler.postWriter.setHeaders(URLConnection, HTTPSampler)'
0644: */
0645: public void testSetHeaders() throws IOException {
0646: sampler.setMethod(HTTPSamplerBase.POST);
0647: setupFilepart(sampler);
0648: setupFormData(sampler);
0649:
0650: postWriter.setHeaders(connection, sampler);
0651: checkContentTypeMultipart(connection, PostWriter.BOUNDARY);
0652: }
0653:
0654: /*
0655: * Test method for 'org.apache.jmeter.protocol.http.sampler.postWriter.setHeaders(URLConnection, HTTPSampler)'
0656: */
0657: public void testSetHeaders_NoFilename() throws IOException {
0658: setupNoFilename(sampler);
0659: setupFormData(sampler);
0660:
0661: postWriter.setHeaders(connection, sampler);
0662: checkContentTypeUrlEncoded(connection);
0663: checkContentLength(connection,
0664: "title=mytitle&description=mydescription".length());
0665: }
0666:
0667: /**
0668: * setup commons parts of HTTPSampler with a no filename.
0669: *
0670: * @param httpSampler
0671: * @throws IOException
0672: */
0673: private void setupNoFilename(HTTPSampler httpSampler) {
0674: setupFilepart(sampler, "upload", null,
0675: "application/octet-stream");
0676: }
0677:
0678: /**
0679: * Setup the filepart with default values
0680: *
0681: * @param httpSampler
0682: */
0683: private void setupFilepart(HTTPSampler httpSampler) {
0684: setupFilepart(sampler, "upload", temporaryFile, "text/plain");
0685: }
0686:
0687: /**
0688: * Setup the filepart with specified values
0689: *
0690: * @param httpSampler
0691: */
0692: private void setupFilepart(HTTPSampler httpSampler,
0693: String fileField, File file, String mimeType) {
0694: httpSampler.setFileField(fileField);
0695: if (file != null) {
0696: httpSampler.setFilename(file.getAbsolutePath());
0697: } else {
0698: httpSampler.setFilename("");
0699: }
0700: httpSampler.setMimetype(mimeType);
0701: }
0702:
0703: /**
0704: * Setup the form data with default values
0705: *
0706: * @param httpSampler
0707: */
0708: private void setupFormData(HTTPSampler httpSampler) {
0709: setupFormData(httpSampler, "mytitle", "mydescription");
0710: }
0711:
0712: /**
0713: * Setup the form data with specified values
0714: *
0715: * @param httpSampler
0716: */
0717: private void setupFormData(HTTPSampler httpSampler,
0718: String titleValue, String descriptionValue) {
0719: setupFormData(sampler, false, titleValue, descriptionValue);
0720: }
0721:
0722: /**
0723: * Setup the form data with specified values
0724: *
0725: * @param httpSampler
0726: */
0727: private void setupFormData(HTTPSampler httpSampler,
0728: boolean isEncoded, String titleValue,
0729: String descriptionValue) {
0730: Arguments args = new Arguments();
0731: HTTPArgument argument1 = new HTTPArgument("title", titleValue,
0732: isEncoded);
0733: HTTPArgument argument2 = new HTTPArgument("description",
0734: descriptionValue, isEncoded);
0735: args.addArgument(argument1);
0736: args.addArgument(argument2);
0737: httpSampler.setArguments(args);
0738: }
0739:
0740: private void establishConnection() throws MalformedURLException {
0741: connection = new StubURLConnection("http://fake_url/test");
0742: }
0743:
0744: /**
0745: * Create the expected output post body for form data and file multiparts
0746: * with default values for field names
0747: */
0748: private byte[] createExpectedOutput(String boundaryString,
0749: String contentEncoding, String titleValue,
0750: String descriptionValue, byte[] fileContent)
0751: throws IOException {
0752: return createExpectedOutput(boundaryString, contentEncoding,
0753: "title", titleValue, "description", descriptionValue,
0754: "upload", fileContent);
0755: }
0756:
0757: /**
0758: * Create the expected output post body for form data and file multiparts
0759: * with specified values
0760: */
0761: private byte[] createExpectedOutput(String boundaryString,
0762: String contentEncoding, String titleField,
0763: String titleValue, String descriptionField,
0764: String descriptionValue, String fileField,
0765: byte[] fileContent) throws IOException {
0766: // Create the multiparts
0767: byte[] formdataMultipart = createExpectedFormdataOutput(
0768: boundaryString, contentEncoding, titleField,
0769: titleValue, descriptionField, descriptionValue, true,
0770: false);
0771: byte[] fileMultipart = createExpectedFilepartOutput(
0772: boundaryString, fileField, temporaryFile, "text/plain",
0773: fileContent, false, true);
0774:
0775: // Join the two multiparts
0776: ByteArrayOutputStream output = new ByteArrayOutputStream();
0777: output.write(formdataMultipart);
0778: output.write(fileMultipart);
0779:
0780: output.flush();
0781: output.close();
0782:
0783: return output.toByteArray();
0784: }
0785:
0786: /**
0787: * Create the expected output multipart/form-data, with only form data,
0788: * and no file multipart
0789: *
0790: * @param lastMultipart true if this is the last multipart in the request
0791: */
0792: private byte[] createExpectedFormdataOutput(String boundaryString,
0793: String contentEncoding, String titleField,
0794: String titleValue, String descriptionField,
0795: String descriptionValue, boolean firstMultipart,
0796: boolean lastMultipart) throws IOException {
0797: final byte[] DASH_DASH = "--".getBytes(HTTP_ENCODING);
0798: // All form parameter always have text/plain as mime type
0799: final String mimeType = "text/plain";//TODO make this a parameter?
0800:
0801: final ByteArrayOutputStream output = new ByteArrayOutputStream();
0802: if (firstMultipart) {
0803: output.write(DASH_DASH);
0804: output.write(boundaryString.getBytes(HTTP_ENCODING));
0805: output.write(CRLF);
0806: }
0807: output.write("Content-Disposition: form-data; name=\""
0808: .getBytes(HTTP_ENCODING));
0809: output.write(titleField.getBytes(HTTP_ENCODING));
0810: output.write("\"".getBytes(HTTP_ENCODING));
0811: output.write(CRLF);
0812: output.write("Content-Type: ".getBytes(HTTP_ENCODING));
0813: output.write(mimeType.getBytes(HTTP_ENCODING));
0814: output.write("; charset=".getBytes(HTTP_ENCODING));
0815: output.write((contentEncoding == null ? PostWriter.ENCODING
0816: : contentEncoding).getBytes(HTTP_ENCODING));
0817: output.write(CRLF);
0818: output.write("Content-Transfer-Encoding: 8bit"
0819: .getBytes(HTTP_ENCODING));
0820: output.write(CRLF);
0821: output.write(CRLF);
0822: if (contentEncoding != null) {
0823: output.write(titleValue.getBytes(contentEncoding));
0824: } else {
0825: output.write(titleValue.getBytes());
0826: }
0827: output.write(CRLF);
0828: output.write(DASH_DASH);
0829: output.write(boundaryString.getBytes(HTTP_ENCODING));
0830: output.write(CRLF);
0831: output.write("Content-Disposition: form-data; name=\""
0832: .getBytes(HTTP_ENCODING));
0833: output.write(descriptionField.getBytes(HTTP_ENCODING));
0834: output.write("\"".getBytes(HTTP_ENCODING));
0835: output.write(CRLF);
0836: output.write("Content-Type: ".getBytes(HTTP_ENCODING));
0837: output.write(mimeType.getBytes(HTTP_ENCODING));
0838: output.write("; charset=".getBytes(HTTP_ENCODING));
0839: output.write((contentEncoding == null ? PostWriter.ENCODING
0840: : contentEncoding).getBytes(HTTP_ENCODING));
0841: output.write(CRLF);
0842: output.write("Content-Transfer-Encoding: 8bit"
0843: .getBytes(HTTP_ENCODING));
0844: output.write(CRLF);
0845: output.write(CRLF);
0846: if (contentEncoding != null) {
0847: output.write(descriptionValue.getBytes(contentEncoding));
0848: } else {
0849: output.write(descriptionValue.getBytes());
0850: }
0851: output.write(CRLF);
0852: output.write(DASH_DASH);
0853: output.write(boundaryString.getBytes(HTTP_ENCODING));
0854: if (lastMultipart) {
0855: output.write(DASH_DASH);
0856: }
0857: output.write(CRLF);
0858:
0859: output.flush();
0860: output.close();
0861:
0862: return output.toByteArray();
0863: }
0864:
0865: /**
0866: * Create the expected file multipart
0867: *
0868: * @param lastMultipart true if this is the last multipart in the request
0869: */
0870: private byte[] createExpectedFilepartOutput(String boundaryString,
0871: String fileField, File file, String mimeType,
0872: byte[] fileContent, boolean firstMultipart,
0873: boolean lastMultipart) throws IOException {
0874: // The encoding used for http headers and control information
0875: final String httpEncoding = "ISO-8859-1";
0876: final byte[] DASH_DASH = "--".getBytes(httpEncoding);
0877:
0878: final ByteArrayOutputStream output = new ByteArrayOutputStream();
0879: if (firstMultipart) {
0880: output.write(DASH_DASH);
0881: output.write(boundaryString.getBytes(httpEncoding));
0882: output.write(CRLF);
0883: }
0884: // replace all backslash with double backslash
0885: String filename = file.getName();
0886: output.write("Content-Disposition: form-data; name=\""
0887: .getBytes(httpEncoding));
0888: output.write(fileField.getBytes(httpEncoding));
0889: output.write(("\"; filename=\"" + filename + "\"")
0890: .getBytes(httpEncoding));
0891: output.write(CRLF);
0892: output.write("Content-Type: ".getBytes(httpEncoding));
0893: output.write(mimeType.getBytes(httpEncoding));
0894: output.write(CRLF);
0895: output.write("Content-Transfer-Encoding: binary"
0896: .getBytes(httpEncoding));
0897: output.write(CRLF);
0898: output.write(CRLF);
0899: output.write(fileContent);
0900: output.write(CRLF);
0901: output.write(DASH_DASH);
0902: output.write(boundaryString.getBytes(httpEncoding));
0903: if (lastMultipart) {
0904: output.write(DASH_DASH);
0905: }
0906: output.write(CRLF);
0907:
0908: output.flush();
0909: output.close();
0910:
0911: return output.toByteArray();
0912: }
0913:
0914: /**
0915: * Check that the the two byte arrays have identical content
0916: *
0917: * @param expected
0918: * @param actual
0919: * @throws UnsupportedEncodingException
0920: */
0921: private void checkArraysHaveSameContent(byte[] expected,
0922: byte[] actual) throws UnsupportedEncodingException {
0923: if (expected != null && actual != null) {
0924: if (expected.length != actual.length) {
0925: System.out.println(new String(expected, UTF_8));
0926: System.out.println("--------------------");
0927: System.out.println(new String(actual, UTF_8));
0928: System.out.println("====================");
0929: fail("arrays have different length, expected is "
0930: + expected.length + ", actual is "
0931: + actual.length);
0932: } else {
0933: for (int i = 0; i < expected.length; i++) {
0934: if (expected[i] != actual[i]) {
0935: System.out.println(new String(expected, 0,
0936: i + 1));
0937: System.out.println("--------------------");
0938: System.out
0939: .println(new String(actual, 0, i + 1));
0940: System.out.println("====================");
0941: fail("byte at position " + i
0942: + " is different, expected is "
0943: + expected[i] + ", actual is "
0944: + actual[i]);
0945: }
0946: }
0947: }
0948: } else {
0949: fail("expected or actual byte arrays were null");
0950: }
0951: }
0952:
0953: /**
0954: * Check that the the two byte arrays different content
0955: *
0956: * @param expected
0957: * @param actual
0958: */
0959: private void checkArraysHaveDifferentContent(byte[] expected,
0960: byte[] actual) {
0961: if (expected != null && actual != null) {
0962: if (expected.length == actual.length) {
0963: boolean allSame = true;
0964: for (int i = 0; i < expected.length; i++) {
0965: if (expected[i] != actual[i]) {
0966: allSame = false;
0967: break;
0968: }
0969: }
0970: if (allSame) {
0971: fail("all bytes were equal");
0972: }
0973: }
0974: } else {
0975: fail("expected or actual byte arrays were null");
0976: }
0977: }
0978:
0979: private void checkContentTypeMultipart(HttpURLConnection conn,
0980: String boundaryString) {
0981: assertEquals("multipart/form-data; boundary=" + boundaryString,
0982: conn.getRequestProperty("Content-Type"));
0983: }
0984:
0985: private void checkContentTypeUrlEncoded(HttpURLConnection conn) {
0986: assertEquals(HTTPSamplerBase.APPLICATION_X_WWW_FORM_URLENCODED,
0987: conn.getRequestProperty("Content-Type"));
0988: }
0989:
0990: private void checkContentLength(HttpURLConnection conn, int length) {
0991: assertEquals(Integer.toString(length), conn
0992: .getRequestProperty("Content-Length"));
0993: }
0994:
0995: /**
0996: * Mock an HttpURLConnection.
0997: * extends HttpURLConnection instead of just URLConnection because there is a cast in PostWriter.
0998: */
0999: private static class StubURLConnection extends HttpURLConnection {
1000: private ByteArrayOutputStream output = new ByteArrayOutputStream();
1001: private Map properties = new HashMap();
1002:
1003: public StubURLConnection(String url)
1004: throws MalformedURLException {
1005: super (new URL(url));
1006: }
1007:
1008: public void connect() throws IOException {
1009: }
1010:
1011: public OutputStream getOutputStream() throws IOException {
1012: return output;
1013: }
1014:
1015: public void disconnect() {
1016: }
1017:
1018: public boolean usingProxy() {
1019: return false;
1020: }
1021:
1022: public String getRequestProperty(String key) {
1023: return (String) properties.get(key);
1024: }
1025:
1026: public void setRequestProperty(String key, String value) {
1027: properties.put(key, value);
1028: }
1029:
1030: public byte[] getOutputStreamContent() {
1031: return output.toByteArray();
1032: }
1033: }
1034: }
|