View | Details | Raw Unified | Return to bug 27780
Collapse All | Expand All

(-)C:/Documents and Settings/alf.hogemark/workspace/Jmeter 2.2/test/src/org/apache/jmeter/protocol/http/sampler/TestHTTPSamplersAgainstHttpMirrorServer.java (+514 lines)
Line 0 Link Here
1
/*
2
 * Licensed to the Apache Software Foundation (ASF) under one or more
3
 * contributor license agreements.  See the NOTICE file distributed with
4
 * this work for additional information regarding copyright ownership.
5
 * The ASF licenses this file to You under the Apache License, Version 2.0
6
 * (the "License"); you may not use this file except in compliance with
7
 * the License.  You may obtain a copy of the License at
8
 *
9
 *   http://www.apache.org/licenses/LICENSE-2.0
10
 *
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 * 
17
 */
18
19
package org.apache.jmeter.protocol.http.sampler;
20
21
import java.io.ByteArrayOutputStream;
22
import java.io.IOException;
23
import java.net.URLEncoder;
24
import java.util.Locale;
25
26
import org.apache.jmeter.config.Arguments;
27
import org.apache.jmeter.engine.util.ValueReplacer;
28
import org.apache.jmeter.protocol.http.control.HttpMirrorControl;
29
import org.apache.jmeter.protocol.http.util.HTTPArgument;
30
import org.apache.jmeter.testelement.TestPlan;
31
import org.apache.jmeter.threads.JMeterContextService;
32
import org.apache.jmeter.threads.JMeterVariables;
33
import org.apache.jmeter.util.JMeterUtils;
34
import org.apache.oro.text.regex.MatchResult;
35
import org.apache.oro.text.regex.Pattern;
36
import org.apache.oro.text.regex.PatternMatcherInput;
37
import org.apache.oro.text.regex.Perl5Compiler;
38
import org.apache.oro.text.regex.Perl5Matcher;
39
40
import junit.framework.TestCase;
41
42
/**
43
 * Class for performing actual samples for HTTPSampler and HTTPSampler2.
44
 * The samples are executed against the HttpMirrorServer, which is 
45
 * started when the unit tests are executed.
46
 */
47
public class TestHTTPSamplersAgainstHttpMirrorServer extends TestCase {
48
    private final static int HTTP_SAMPLER = 0;
49
    private final static int HTTP_SAMPLER2 = 1;
50
    private HttpMirrorControl webServerControl;
51
    private int webServerPort = 8080;
52
53
    public TestHTTPSamplersAgainstHttpMirrorServer(String arg0) {
54
        super(arg0);
55
    }
56
    protected void setUp() throws Exception {
57
        webServerControl = new HttpMirrorControl();
58
        webServerControl.setPort(webServerPort);
59
        webServerControl.startHttpMirror();
60
    }
61
62
    protected void tearDown() throws Exception {
63
        // Shutdown web server
64
        webServerControl.stopHttpMirror();
65
        webServerControl = null;
66
    }
67
        
68
    public void testPostRequest_UrlEncoded() throws Exception {
69
        // Test HTTPSampler
70
        String samplerDefaultEncoding = "ISO-8859-1".toLowerCase();
71
        testPostRequest_UrlEncoded(HTTP_SAMPLER, samplerDefaultEncoding);
72
        
73
        // Test HTTPSampler2
74
        samplerDefaultEncoding = "US-ASCII";
75
        testPostRequest_UrlEncoded(HTTP_SAMPLER2, samplerDefaultEncoding);
76
    }
77
    
78
    public void testPostRequest_FormMultipart() throws Exception {
79
        // Test HTTPSampler
80
        String samplerDefaultEncoding = "ISO-8859-1".toLowerCase();
81
        testPostRequest_FormMultipart(HTTP_SAMPLER, samplerDefaultEncoding);
82
        
83
        // Test HTTPSampler2
84
        samplerDefaultEncoding = "US-ASCII";
85
        testPostRequest_FormMultipart(HTTP_SAMPLER2, samplerDefaultEncoding);
86
    }
87
88
    private void testPostRequest_UrlEncoded(int samplerType, String samplerDefaultEncoding) throws Exception {
89
        String titleField = "title";
90
        String titleValue = "mytitle";
91
        String descriptionField = "description";
92
        String descriptionValue = "mydescription";
93
94
        // Test sending data with default encoding
95
        HTTPSamplerBase sampler = createHttpSampler(samplerType);
96
        String contentEncoding = "";
97
        setupUrl(sampler, contentEncoding);
98
        setupFormData(sampler, false, titleField, titleValue, descriptionField, descriptionValue);
99
        HTTPSampleResult res = executeSampler(sampler);
100
        checkPostRequestUrlEncoded(sampler, res, samplerDefaultEncoding, contentEncoding, titleField, titleValue, descriptionField, descriptionValue);
101
        
102
        // Test sending data as ISO-8859-1
103
        sampler = createHttpSampler(samplerType);
104
        contentEncoding = "ISO-8859-1";
105
        setupUrl(sampler, contentEncoding);
106
        setupFormData(sampler, false, titleField, titleValue, descriptionField, descriptionValue);
107
        res = executeSampler(sampler);
108
        checkPostRequestUrlEncoded(sampler, res, samplerDefaultEncoding, contentEncoding, titleField, titleValue, descriptionField, descriptionValue);
109
110
        // Test sending data as UTF-8
111
        sampler = createHttpSampler(samplerType);
112
        contentEncoding = "UTF-8";
113
        titleValue = "mytitle\u0153\u20a1\u0115\u00c5";
114
        descriptionValue = "mydescription\u0153\u20a1\u0115\u00c5";
115
        setupUrl(sampler, contentEncoding);
116
        setupFormData(sampler, false, titleField, titleValue, descriptionField, descriptionValue);
117
        res = executeSampler(sampler);
118
        checkPostRequestUrlEncoded(sampler, res, samplerDefaultEncoding, contentEncoding, titleField, titleValue, descriptionField, descriptionValue);
119
120
        // Test sending data as UTF-8, where user defined variables are used
121
        // to set the value for form data
122
        JMeterUtils.setLocale(Locale.ENGLISH);
123
        TestPlan testPlan = new TestPlan();
124
        JMeterVariables vars = new JMeterVariables();
125
        vars.put("title_prefix", "a test\u00c5");
126
        vars.put("description_suffix", "the_end");
127
        JMeterContextService.getContext().setVariables(vars);
128
        JMeterContextService.getContext().setSamplingStarted(true);
129
        ValueReplacer replacer = new ValueReplacer();
130
        replacer.setUserDefinedVariables(testPlan.getUserDefinedVariables());
131
        
132
        sampler = createHttpSampler(samplerType);
133
        contentEncoding = "UTF-8";
134
        titleValue = "${title_prefix}mytitle\u0153\u20a1\u0115\u00c5";
135
        descriptionValue = "mydescription\u0153\u20a1\u0115\u00c5${description_suffix}";
136
        setupUrl(sampler, contentEncoding);
137
        setupFormData(sampler, false, titleField, titleValue, descriptionField, descriptionValue);
138
        // Replace the variables in the sampler
139
        replacer.replaceValues(sampler);
140
        res = executeSampler(sampler);
141
        String expectedTitleValue = "a test\u00c5mytitle\u0153\u20a1\u0115\u00c5";
142
        String expectedDescriptionValue = "mydescription\u0153\u20a1\u0115\u00c5the_end";
143
        checkPostRequestUrlEncoded(sampler, res, samplerDefaultEncoding, contentEncoding, titleField, expectedTitleValue, descriptionField, expectedDescriptionValue);
144
    }
145
146
    private void testPostRequest_FormMultipart(int samplerType, String samplerDefaultEncoding) throws Exception {
147
        String titleField = "title";
148
        String titleValue = "mytitle";
149
        String descriptionField = "description";
150
        String descriptionValue = "mydescription";
151
152
        // Test sending data with default encoding
153
        HTTPSamplerBase sampler = createHttpSampler(samplerType);
154
        String contentEncoding = "";
155
        setupUrl(sampler, contentEncoding);
156
        setupFormData(sampler, false, titleField, titleValue, descriptionField, descriptionValue);
157
        sampler.setDoMultipartPost(true);
158
        HTTPSampleResult res = executeSampler(sampler);
159
        checkPostRequestFormMultipart(sampler, res, samplerDefaultEncoding, contentEncoding, titleField, titleValue, descriptionField, descriptionValue);
160
        
161
        // Test sending data as ISO-8859-1
162
        sampler = createHttpSampler(samplerType);
163
        contentEncoding = "ISO-8859-1";
164
        setupUrl(sampler, contentEncoding);
165
        setupFormData(sampler, false, titleField, titleValue, descriptionField, descriptionValue);
166
        sampler.setDoMultipartPost(true);
167
        res = executeSampler(sampler);
168
        checkPostRequestFormMultipart(sampler, res, samplerDefaultEncoding, contentEncoding, titleField, titleValue, descriptionField, descriptionValue);
169
170
        // Test sending data as UTF-8
171
        sampler = createHttpSampler(samplerType);
172
        contentEncoding = "UTF-8";
173
        titleValue = "mytitle\u0153\u20a1\u0115\u00c5";
174
        descriptionValue = "mydescription\u0153\u20a1\u0115\u00c5";
175
        setupUrl(sampler, contentEncoding);
176
        setupFormData(sampler, false, titleField, titleValue, descriptionField, descriptionValue);
177
        sampler.setDoMultipartPost(true);
178
        res = executeSampler(sampler);
179
        checkPostRequestFormMultipart(sampler, res, samplerDefaultEncoding, contentEncoding, titleField, titleValue, descriptionField, descriptionValue);
180
        
181
        // Test sending data as UTF-8, with values that would have been urlencoded
182
        // if it was not sent as multipart
183
        sampler = createHttpSampler(samplerType);
184
        contentEncoding = "UTF-8";
185
        titleValue = "mytitle\u0153+\u20a1 \u0115&yes\u00c5";
186
        descriptionValue = "mydescription \u0153 \u20a1 \u0115 \u00c5";
187
        setupUrl(sampler, contentEncoding);
188
        setupFormData(sampler, false, titleField, titleValue, descriptionField, descriptionValue);
189
        sampler.setDoMultipartPost(true);
190
        res = executeSampler(sampler);
191
        checkPostRequestFormMultipart(sampler, res, samplerDefaultEncoding, contentEncoding, titleField, titleValue, descriptionField, descriptionValue);
192
193
        // Test sending data as UTF-8, where user defined variables are used
194
        // to set the value for form data
195
        JMeterUtils.setLocale(Locale.ENGLISH);
196
        TestPlan testPlan = new TestPlan();
197
        JMeterVariables vars = new JMeterVariables();
198
        vars.put("title_prefix", "a test\u00c5");
199
        vars.put("description_suffix", "the_end");
200
        JMeterContextService.getContext().setVariables(vars);
201
        JMeterContextService.getContext().setSamplingStarted(true);
202
        ValueReplacer replacer = new ValueReplacer();
203
        replacer.setUserDefinedVariables(testPlan.getUserDefinedVariables());
204
        
205
        sampler = createHttpSampler(samplerType);
206
        contentEncoding = "UTF-8";
207
        titleValue = "${title_prefix}mytitle\u0153\u20a1\u0115\u00c5";
208
        descriptionValue = "mydescription\u0153\u20a1\u0115\u00c5${description_suffix}";
209
        setupUrl(sampler, contentEncoding);
210
        setupFormData(sampler, false, titleField, titleValue, descriptionField, descriptionValue);
211
        sampler.setDoMultipartPost(true);
212
        // Replace the variables in the sampler
213
        replacer.replaceValues(sampler);
214
        res = executeSampler(sampler);
215
        String expectedTitleValue = "a test\u00c5mytitle\u0153\u20a1\u0115\u00c5";
216
        String expectedDescriptionValue = "mydescription\u0153\u20a1\u0115\u00c5the_end";
217
        checkPostRequestFormMultipart(sampler, res, samplerDefaultEncoding, contentEncoding, titleField, expectedTitleValue, descriptionField, expectedDescriptionValue);
218
    }
219
    
220
    private HTTPSampleResult executeSampler(HTTPSamplerBase sampler) {
221
        sampler.setRunningVersion(true);
222
        sampler.threadStarted();
223
        HTTPSampleResult res = (HTTPSampleResult) sampler.sample();
224
        sampler.threadFinished();
225
        sampler.setRunningVersion(false);
226
        return res;
227
    }
228
    
229
    private void checkPostRequestUrlEncoded(
230
            HTTPSamplerBase sampler,
231
            HTTPSampleResult res,
232
            String samplerDefaultEncoding,
233
            String contentEncoding,
234
            String titleField,
235
            String titleValue,
236
            String descriptionField,
237
            String descriptionValue) throws IOException {
238
        if(contentEncoding == null || contentEncoding.length() == 0) {
239
            contentEncoding = samplerDefaultEncoding;
240
        }
241
        // Check URL
242
        assertEquals(sampler.getUrl(), res.getURL());
243
        String expectedPostBody = titleField + "=" + URLEncoder.encode(titleValue, contentEncoding) + "&" + descriptionField + "=" + URLEncoder.encode(descriptionValue, contentEncoding);
244
        // Check request headers
245
        assertTrue(isInRequestHeaders(res.getRequestHeaders(), HTTPSamplerBase.HEADER_CONTENT_TYPE, HTTPSamplerBase.APPLICATION_X_WWW_FORM_URLENCODED));
246
        assertTrue(
247
                isInRequestHeaders(
248
                        res.getRequestHeaders(),
249
                        HTTPSamplerBase.HEADER_CONTENT_LENGTH,
250
                        Integer.toString(expectedPostBody.getBytes(contentEncoding).length)
251
                )
252
        );
253
        // Check post body from the result query string
254
        checkArraysHaveSameContent(expectedPostBody.getBytes(contentEncoding), res.getQueryString().getBytes(contentEncoding));
255
256
        // Find the data sent to the mirror server, which the mirror server is sending back to us
257
        String dataSentToMirrorServer = new String(res.getResponseData(), contentEncoding);
258
        int posDividerHeadersAndBody = getPositionOfBody(dataSentToMirrorServer);
259
        String headersSent = null;
260
        String bodySent = null;
261
        if(posDividerHeadersAndBody >= 0) {
262
            headersSent = dataSentToMirrorServer.substring(0, posDividerHeadersAndBody);
263
            // Skip the blank line with crlf dividing headers and body
264
            bodySent = dataSentToMirrorServer.substring(posDividerHeadersAndBody+2);
265
        }
266
        // Check response headers
267
        assertTrue(isInRequestHeaders(headersSent, HTTPSamplerBase.HEADER_CONTENT_TYPE, HTTPSamplerBase.APPLICATION_X_WWW_FORM_URLENCODED));
268
        assertTrue(
269
                isInRequestHeaders(
270
                        headersSent,
271
                        HTTPSamplerBase.HEADER_CONTENT_LENGTH,
272
                        Integer.toString(expectedPostBody.getBytes(contentEncoding).length)
273
                )
274
        );
275
        // Check post body which was sent to the mirror server, and
276
        // sent back by the mirror server
277
        checkArraysHaveSameContent(expectedPostBody.getBytes(contentEncoding), bodySent.getBytes(contentEncoding));
278
    }
279
280
    private void checkPostRequestFormMultipart(
281
            HTTPSamplerBase sampler,
282
            HTTPSampleResult res,
283
            String samplerDefaultEncoding,
284
            String contentEncoding,
285
            String titleField,
286
            String titleValue,
287
            String descriptionField,
288
            String descriptionValue) throws IOException {
289
        if(contentEncoding == null || contentEncoding.length() == 0) {
290
            contentEncoding = samplerDefaultEncoding;
291
        }
292
        // Check URL
293
        assertEquals(sampler.getUrl(), res.getURL());
294
        String boundaryString = getBoundaryStringFromContentType(res.getRequestHeaders());
295
        assertNotNull(boundaryString);
296
        byte[] expectedPostBody = createExpectedFormdataOutput(boundaryString, contentEncoding, titleField, titleValue, descriptionField, descriptionValue, true, true);
297
        // Check request headers
298
        assertTrue(isInRequestHeaders(res.getRequestHeaders(), HTTPSamplerBase.HEADER_CONTENT_TYPE, HTTPSamplerBase.MULTIPART_FORM_DATA + "; boundary=" + boundaryString));
299
        assertTrue(
300
                isInRequestHeaders(
301
                        res.getRequestHeaders(),
302
                        HTTPSamplerBase.HEADER_CONTENT_LENGTH,
303
                        Integer.toString(expectedPostBody.length)
304
                )
305
        );
306
        // Check post body from the result query string
307
        checkArraysHaveSameContent(expectedPostBody, res.getQueryString().getBytes(contentEncoding));
308
309
        // Find the data sent to the mirror server, which the mirror server is sending back to us
310
        String dataSentToMirrorServer = new String(res.getResponseData(), contentEncoding);
311
        int posDividerHeadersAndBody = getPositionOfBody(dataSentToMirrorServer);
312
        String headersSent = null;
313
        String bodySent = null;
314
        if(posDividerHeadersAndBody >= 0) {
315
            headersSent = dataSentToMirrorServer.substring(0, posDividerHeadersAndBody);
316
            // Skip the blank line with crlf dividing headers and body
317
            bodySent = dataSentToMirrorServer.substring(posDividerHeadersAndBody+2);
318
        }
319
        // Check response headers
320
        assertTrue(isInRequestHeaders(headersSent, HTTPSamplerBase.HEADER_CONTENT_TYPE, HTTPSamplerBase.MULTIPART_FORM_DATA + "; boundary=" + boundaryString));
321
        assertTrue(
322
                isInRequestHeaders(
323
                        headersSent,
324
                        HTTPSamplerBase.HEADER_CONTENT_LENGTH,
325
                        Integer.toString(expectedPostBody.length)
326
                )
327
        );
328
        // Check post body which was sent to the mirror server, and
329
        // sent back by the mirror server
330
        checkArraysHaveSameContent(expectedPostBody, bodySent.getBytes(contentEncoding));
331
    }    
332
333
    private boolean isInRequestHeaders(String requestHeaders, String headerName, String headerValue) {
334
        return checkRegularExpression(requestHeaders, headerName + ": " + headerValue);
335
    }
336
337
    private boolean checkRegularExpression(String stringToCheck, String regularExpression) {
338
        Perl5Matcher localMatcher = JMeterUtils.getMatcher();
339
        Pattern pattern = JMeterUtils.getPattern(regularExpression, Perl5Compiler.READ_ONLY_MASK | Perl5Compiler.CASE_INSENSITIVE_MASK | Perl5Compiler.SINGLELINE_MASK);
340
        return localMatcher.contains(stringToCheck, pattern);
341
    }
342
343
    private int getPositionOfBody(String stringToCheck) {
344
        Perl5Matcher localMatcher = JMeterUtils.getMatcher();
345
        // The headers and body are divided by a blank line
346
        String regularExpression = "^.$"; 
347
        Pattern pattern = JMeterUtils.getPattern(regularExpression, Perl5Compiler.READ_ONLY_MASK | Perl5Compiler.CASE_INSENSITIVE_MASK | Perl5Compiler.MULTILINE_MASK);
348
        
349
        PatternMatcherInput input = new PatternMatcherInput(stringToCheck);
350
        while(localMatcher.contains(input, pattern)) {
351
            MatchResult match = localMatcher.getMatch();
352
            return match.beginOffset(0);
353
        }
354
        // No divider was found
355
        return -1;
356
    }
357
358
    private String getBoundaryStringFromContentType(String requestHeaders) {
359
        Perl5Matcher localMatcher = JMeterUtils.getMatcher();
360
        String regularExpression = "^" + HTTPSamplerBase.HEADER_CONTENT_TYPE + ": multipart/form-data; boundary=(.+)$"; 
361
        Pattern pattern = JMeterUtils.getPattern(regularExpression, Perl5Compiler.READ_ONLY_MASK | Perl5Compiler.CASE_INSENSITIVE_MASK | Perl5Compiler.MULTILINE_MASK);
362
        if(localMatcher.contains(requestHeaders, pattern)) {
363
            MatchResult match = localMatcher.getMatch();
364
            return match.group(1);
365
        }
366
        else {
367
            return null;
368
        }
369
    }
370
371
    private void setupUrl(HTTPSamplerBase sampler, String contentEncoding) {
372
        String protocol = "http";
373
        // String domain = "localhost";
374
        String domain = "localhost";
375
        String path = "/test/somescript.jsp";
376
        int port = 8080;
377
        sampler.setProtocol(protocol);
378
        sampler.setMethod(HTTPSamplerBase.POST);
379
        sampler.setPath(path);
380
        sampler.setDomain(domain);
381
        sampler.setPort(port);
382
        sampler.setContentEncoding(contentEncoding);
383
    }
384
385
    /**
386
     * Setup the form data with specified values
387
     * 
388
     * @param httpSampler
389
     */
390
    private void setupFormData(HTTPSamplerBase httpSampler, boolean isEncoded, String titleField, String titleValue, String descriptionField, String descriptionValue) {
391
        Arguments args = new Arguments();
392
        HTTPArgument argument1 = new HTTPArgument(titleField, titleValue, isEncoded);
393
        HTTPArgument argument2 = new HTTPArgument(descriptionField, descriptionValue, isEncoded);
394
        args.addArgument(argument1);
395
        args.addArgument(argument2);
396
        httpSampler.setArguments(args);
397
    }
398
399
    /**
400
     * Check that the the two byte arrays have identical content
401
     * 
402
     * @param expected
403
     * @param actual
404
     */
405
    private void checkArraysHaveSameContent(byte[] expected, byte[] actual) {
406
        if(expected != null && actual != null) {
407
            if(expected.length != actual.length) {
408
                fail("arrays have different length, expected is " + expected.length + ", actual is " + actual.length);
409
            }
410
            else {
411
                for(int i = 0; i < expected.length; i++) {
412
                    if(expected[i] != actual[i]) {
413
                        fail("byte at position " + i + " is different, expected is " + expected[i] + ", actual is " + actual[i]);
414
                    }
415
                }
416
            }
417
        }
418
        else {
419
            fail("expected or actual byte arrays were null");
420
        }
421
    }
422
    
423
    /**
424
     * Create the expected output multipart/form-data, with only form data,
425
     * and no file multipart.
426
     * This method is copied from the PostWriterTest class
427
     * 
428
     * @param lastMultipart true if this is the last multipart in the request
429
     */
430
    private byte[] createExpectedFormdataOutput(
431
            String boundaryString,
432
            String contentEncoding,
433
            String titleField,
434
            String titleValue,
435
            String descriptionField,
436
            String descriptionValue,
437
            boolean firstMultipart,
438
            boolean lastMultipart) throws IOException {
439
        // The encoding used for http headers and control information
440
        final String httpEncoding = "ISO-8859-1";
441
        final byte[] CRLF = { 0x0d, 0x0A };
442
        final byte[] DASH_DASH = new String("--").getBytes(httpEncoding);
443
        
444
        final ByteArrayOutputStream output = new ByteArrayOutputStream();
445
        if(firstMultipart) {
446
            output.write(DASH_DASH);
447
            output.write(boundaryString.getBytes(httpEncoding));
448
            output.write(CRLF);
449
        }
450
        output.write("Content-Disposition: form-data; name=\"".getBytes(httpEncoding));
451
        output.write(titleField.getBytes(httpEncoding));
452
        output.write("\"".getBytes(httpEncoding));
453
        output.write(CRLF);
454
        output.write("Content-Type: text/plain".getBytes(httpEncoding));
455
        if(contentEncoding != null) {
456
            output.write("; charset=".getBytes(httpEncoding));
457
            output.write(contentEncoding.getBytes(httpEncoding));
458
        }
459
        output.write(CRLF);
460
        output.write("Content-Transfer-Encoding: 8bit".getBytes(httpEncoding));
461
        output.write(CRLF);
462
        output.write(CRLF);
463
        if(contentEncoding != null) {
464
            output.write(titleValue.getBytes(contentEncoding));
465
        }
466
        else {
467
            output.write(titleValue.getBytes());
468
        }
469
        output.write(CRLF);
470
        output.write(DASH_DASH);
471
        output.write(boundaryString.getBytes(httpEncoding));
472
        output.write(CRLF);
473
        output.write("Content-Disposition: form-data; name=\"".getBytes(httpEncoding));
474
        output.write(descriptionField.getBytes(httpEncoding));
475
        output.write("\"".getBytes(httpEncoding));
476
        output.write(CRLF);
477
        output.write("Content-Type: text/plain".getBytes(httpEncoding));
478
        if(contentEncoding != null) {
479
            output.write("; charset=".getBytes(httpEncoding));
480
            output.write(contentEncoding.getBytes(httpEncoding));
481
        }
482
        output.write(CRLF);
483
        output.write("Content-Transfer-Encoding: 8bit".getBytes(httpEncoding));
484
        output.write(CRLF);
485
        output.write(CRLF);
486
        if(contentEncoding != null) {
487
            output.write(descriptionValue.getBytes(contentEncoding));
488
        }
489
        else {
490
            output.write(descriptionValue.getBytes());
491
        }
492
        output.write(CRLF);
493
        output.write(DASH_DASH);
494
        output.write(boundaryString.getBytes(httpEncoding));
495
        if(lastMultipart) {
496
            output.write(DASH_DASH);
497
        }
498
        output.write(CRLF);
499
                
500
        output.flush();
501
        output.close();
502
503
        return output.toByteArray();
504
    }
505
    
506
    private HTTPSamplerBase createHttpSampler(int samplerType) {
507
        if(samplerType == HTTP_SAMPLER2) {
508
            return new HTTPSampler2();
509
        }
510
        else {
511
            return new HTTPSampler();
512
        }
513
    }
514
}
(-)C:/Documents and Settings/alf.hogemark/workspace/Jmeter 2.2/test/src/org/apache/jmeter/protocol/http/sampler/PostWriterTest.java (-67 / +715 lines)
Lines 26-32 Link Here
26
import java.net.HttpURLConnection;
26
import java.net.HttpURLConnection;
27
import java.net.MalformedURLException;
27
import java.net.MalformedURLException;
28
import java.net.URL;
28
import java.net.URL;
29
import java.net.URLConnection;
29
import java.net.URLDecoder;
30
import java.net.URLEncoder;
30
import java.util.HashMap;
31
import java.util.HashMap;
31
import java.util.Map;
32
import java.util.Map;
32
33
Lines 38-57 Link Here
38
public class PostWriterTest extends TestCase {
39
public class PostWriterTest extends TestCase {
39
    
40
    
40
    private final static byte[] CRLF = { 0x0d, 0x0A };
41
    private final static byte[] CRLF = { 0x0d, 0x0A };
42
    private static byte[] TEST_FILE_CONTENT;
41
    
43
    
42
    private URLConnection connection;
44
    private StubURLConnection connection;
43
    private HTTPSampler sampler;
45
    private HTTPSampler sampler;
44
    private File temporaryFile;
46
    private File temporaryFile;
47
    private PostWriter postWriter;
45
    
48
    
46
    protected void setUp() throws Exception {
49
    protected void setUp() throws Exception {
47
        connection = new StubURLConnection("http://fake_url/test");
50
        establishConnection();
48
        sampler = new HTTPSampler();// This must be the original (Java) HTTP sampler
51
        sampler = new HTTPSampler();// This must be the original (Java) HTTP sampler
49
        
52
        
53
        // Create the test file content
54
        TEST_FILE_CONTENT = new String("foo content &?=01234+56789-\u007c\u2aa1\u266a\u0153\u20a1\u0115\u0364\u00c5\u2052").getBytes("UTF-8");
55
50
        // create a temporary file to make sure we always have a file to give to the PostWriter 
56
        // create a temporary file to make sure we always have a file to give to the PostWriter 
51
        // Whereever we are or Whatever the current path is.
57
        // Whereever we are or Whatever the current path is.
52
        temporaryFile = File.createTempFile("foo", "txt");
58
        temporaryFile = File.createTempFile("foo", "txt");
53
        OutputStream output = new FileOutputStream(temporaryFile);
59
        OutputStream output = new FileOutputStream(temporaryFile);
54
        output.write("foo content".getBytes());
60
        output.write(TEST_FILE_CONTENT);
55
        output.flush();
61
        output.flush();
56
        output.close();
62
        output.close();
57
    }
63
    }
Lines 63-100 Link Here
63
69
64
    /*
70
    /*
65
     * Test method for 'org.apache.jmeter.protocol.http.sampler.PostWriter.sendPostData(URLConnection, HTTPSampler)'
71
     * Test method for 'org.apache.jmeter.protocol.http.sampler.PostWriter.sendPostData(URLConnection, HTTPSampler)'
72
     * This method test sending a request which contains both formdata and file content
66
     */
73
     */
67
    public void testSendPostData() throws IOException {
74
    public void testSendPostData() throws IOException {
68
        setupFilename(sampler);
75
        setupFilepart(sampler);
69
        setupCommons(sampler);
76
        String titleValue = "mytitle";
77
        String descriptionValue = "mydescription";
78
        setupFormData(sampler, titleValue, descriptionValue);
70
        
79
        
71
        PostWriter.sendPostData(connection, sampler);
80
        // Test sending data with default encoding
81
        String contentEncoding = "";
82
        sampler.setContentEncoding(contentEncoding);        
83
        postWriter.setHeaders(connection, sampler);
84
        postWriter.sendPostData(connection, sampler);
85
86
        checkContentTypeMultipart(connection, postWriter.getBoundary());
87
        byte[] expectedFormBody = createExpectedOutput(postWriter.getBoundary(), "iso-8859-1", titleValue, descriptionValue, TEST_FILE_CONTENT);
88
        checkContentLength(connection, expectedFormBody.length);        
89
        checkArraysHaveSameContent(expectedFormBody, connection.getOutputStreamContent());
90
        connection.disconnect();
91
92
        // Test sending data as ISO-8859-1
93
        establishConnection();
94
        contentEncoding = "ISO-8859-1";
95
        sampler.setContentEncoding(contentEncoding);        
96
        postWriter.setHeaders(connection, sampler);
97
        postWriter.sendPostData(connection, sampler);
98
99
        checkContentTypeMultipart(connection, postWriter.getBoundary());
100
        expectedFormBody = createExpectedOutput(postWriter.getBoundary(), contentEncoding, titleValue, descriptionValue, TEST_FILE_CONTENT);
101
        checkContentLength(connection, expectedFormBody.length);        
102
        checkArraysHaveSameContent(expectedFormBody, connection.getOutputStreamContent());
103
        connection.disconnect();
72
        
104
        
73
        assertEquals(createExpectedOutputStream().toString(), connection.getOutputStream().toString());
105
        // Test sending data as UTF-8
106
        establishConnection();
107
        titleValue = "mytitle\u0153\u20a1\u0115\u00c5";
108
        descriptionValue = "mydescription\u0153\u20a1\u0115\u00c5";
109
        contentEncoding = "UTF-8";
110
        sampler.setContentEncoding(contentEncoding);        
111
        setupFormData(sampler, titleValue, descriptionValue);
112
        postWriter.setHeaders(connection, sampler);
113
        postWriter.sendPostData(connection, sampler);
114
        checkContentTypeMultipart(connection, postWriter.getBoundary());
115
        expectedFormBody = createExpectedOutput(postWriter.getBoundary(), contentEncoding, titleValue, descriptionValue, TEST_FILE_CONTENT);
116
        checkContentLength(connection, expectedFormBody.length);        
117
        checkArraysHaveSameContent(expectedFormBody, connection.getOutputStreamContent());
118
        connection.disconnect();
119
120
        // Test sending UTF-8 data with ISO-8859-1 content encoding
121
        establishConnection();
122
        contentEncoding = "UTF-8";
123
        sampler.setContentEncoding("ISO-8859-1");
124
        postWriter.setHeaders(connection, sampler);
125
        postWriter.sendPostData(connection, sampler);
126
        checkContentTypeMultipart(connection, postWriter.getBoundary());
127
        expectedFormBody = createExpectedOutput(postWriter.getBoundary(), contentEncoding, titleValue, descriptionValue, TEST_FILE_CONTENT);
128
        checkContentLength(connection, expectedFormBody.length);        
129
        checkArraysHaveDifferentContent(expectedFormBody, connection.getOutputStreamContent());
130
        connection.disconnect();
74
    }
131
    }
75
132
76
    /*
133
    /*
77
     * Test method for 'org.apache.jmeter.protocol.http.sampler.PostWriter.sendPostData(URLConnection, HTTPSampler)'
134
     * Test method for 'org.apache.jmeter.protocol.http.sampler.PostWriter.sendPostData(URLConnection, HTTPSampler)'
135
     * This method test sending a HTTPSampler with form parameters, and only
136
     * the filename of a file.
78
     */
137
     */
79
    public void testSendPostData_NoFilename() throws IOException {
138
    public void testSendPostData_NoFilename() throws IOException {
80
        setupNoFilename(sampler);
139
        setupNoFilename(sampler);
81
        setupCommons(sampler);
140
        String titleValue = "mytitle";
141
        String descriptionValue = "mydescription";
142
        setupFormData(sampler, titleValue, descriptionValue);
82
143
83
        PostWriter.sendPostData(connection, sampler);
144
        // Test sending data with default encoding
145
        String contentEncoding = "";
146
        sampler.setContentEncoding(contentEncoding);        
147
        postWriter.setHeaders(connection, sampler);
148
        postWriter.sendPostData(connection, sampler);
84
        
149
        
85
        assertEquals("title=mytitle&description=mydescription", connection.getOutputStream().toString());
150
        checkContentTypeUrlEncoded(connection);
151
        byte[] expectedUrl = "title=mytitle&description=mydescription".getBytes();
152
        checkContentLength(connection, expectedUrl.length);
153
        checkArraysHaveSameContent(expectedUrl, connection.getOutputStreamContent());
154
        expectedUrl = "title=mytitle&description=mydescription".getBytes("UTF-8");
155
        checkContentLength(connection, expectedUrl.length);
156
        checkArraysHaveSameContent(expectedUrl, connection.getOutputStreamContent());
157
        connection.disconnect();
158
159
        // Test sending data as ISO-8859-1
160
        establishConnection();
161
        contentEncoding = "ISO-8859-1";
162
        sampler.setContentEncoding(contentEncoding);        
163
        postWriter.setHeaders(connection, sampler);
164
        postWriter.sendPostData(connection, sampler);
165
        
166
        checkContentTypeUrlEncoded(connection);
167
        expectedUrl = "title=mytitle&description=mydescription".getBytes(contentEncoding);
168
        checkContentLength(connection, expectedUrl.length);
169
        checkArraysHaveSameContent(expectedUrl, connection.getOutputStreamContent());
170
        expectedUrl = "title=mytitle&description=mydescription".getBytes("UTF-8");
171
        checkContentLength(connection, expectedUrl.length);
172
        checkArraysHaveSameContent(expectedUrl, connection.getOutputStreamContent());
173
        connection.disconnect();
86
    }
174
    }
87
175
88
    /*
176
    /*
177
     * Test method for 'org.apache.jmeter.protocol.http.sampler.PostWriter.sendPostData(URLConnection, HTTPSampler)'
178
     * This method test sending file content as the only content of the post body
179
     */
180
    public void testSendPostData_FileAsBody() throws IOException {
181
        setupFilepart(sampler, "", temporaryFile, "");
182
        
183
        // Check using default encoding
184
        postWriter.setHeaders(connection, sampler);
185
        postWriter.sendPostData(connection, sampler);
186
187
        checkContentLength(connection, TEST_FILE_CONTENT.length);        
188
        checkArraysHaveSameContent(TEST_FILE_CONTENT, connection.getOutputStreamContent());
189
        connection.disconnect();
190
        
191
        // Check using UTF-8 encoding
192
        establishConnection();
193
        sampler.setContentEncoding("UTF-8");
194
        // File content is sent as binary, so the content encoding should not change the file data
195
        postWriter.setHeaders(connection, sampler);
196
        postWriter.sendPostData(connection, sampler);
197
        
198
        checkContentLength(connection, TEST_FILE_CONTENT.length);        
199
        checkArraysHaveSameContent(TEST_FILE_CONTENT, connection.getOutputStreamContent());
200
        checkArraysHaveDifferentContent(new String(TEST_FILE_CONTENT).getBytes("UTF-8"), connection.getOutputStreamContent());
201
        
202
        // If we have both file as body, and form data, then only form data will be sent
203
        setupFormData(sampler);
204
        establishConnection();
205
        sampler.setContentEncoding("");
206
        postWriter.setHeaders(connection, sampler);
207
        postWriter.sendPostData(connection, sampler);
208
        
209
        checkContentTypeUrlEncoded(connection);
210
        byte[] expectedUrl = "title=mytitle&description=mydescription".getBytes();
211
        checkContentLength(connection, expectedUrl.length);
212
        checkArraysHaveSameContent(expectedUrl, connection.getOutputStreamContent());
213
    }
214
215
    /*
216
     * Test method for 'org.apache.jmeter.protocol.http.sampler.PostWriter.sendPostData(URLConnection, HTTPSampler)'
217
     * This method test sending only a file multipart.
218
     */
219
    public void testSendFileData_Multipart() throws IOException {
220
        String fileField = "upload";
221
        String mimeType = "text/plain";
222
        File file = temporaryFile;
223
        byte[] fileContent = TEST_FILE_CONTENT;
224
        setupFilepart(sampler, fileField, file, mimeType);
225
        
226
        // Test sending data with default encoding
227
        String contentEncoding = "";
228
        sampler.setContentEncoding(contentEncoding);        
229
        postWriter.setHeaders(connection, sampler);
230
        postWriter.sendPostData(connection, sampler);
231
232
        checkContentTypeMultipart(connection, postWriter.getBoundary());
233
        byte[] expectedFormBody = createExpectedFilepartOutput(postWriter.getBoundary(), fileField, file, mimeType, fileContent, true, true);
234
        checkContentLength(connection, expectedFormBody.length);
235
        checkArraysHaveSameContent(expectedFormBody, connection.getOutputStreamContent());
236
        connection.disconnect();
237
238
        // Test sending data as ISO-8859-1
239
        establishConnection();
240
        contentEncoding = "ISO-8859-1";
241
        sampler.setContentEncoding(contentEncoding);        
242
        postWriter.setHeaders(connection, sampler);
243
        postWriter.sendPostData(connection, sampler);
244
245
        checkContentTypeMultipart(connection, postWriter.getBoundary());
246
        expectedFormBody = createExpectedFilepartOutput(postWriter.getBoundary(), fileField, file, mimeType, fileContent, true, true);
247
        checkContentLength(connection, expectedFormBody.length);        
248
        checkArraysHaveSameContent(expectedFormBody, connection.getOutputStreamContent());
249
        connection.disconnect();
250
        
251
        // Test sending data as UTF-8
252
        establishConnection();
253
        fileField = "some_file_field";
254
        mimeType = "image/png";
255
        contentEncoding = "UTF-8";
256
        sampler.setContentEncoding(contentEncoding);        
257
        setupFilepart(sampler, fileField, file, mimeType);
258
        postWriter.setHeaders(connection, sampler);
259
        postWriter.sendPostData(connection, sampler);
260
261
        checkContentTypeMultipart(connection, postWriter.getBoundary());
262
        expectedFormBody = createExpectedFilepartOutput(postWriter.getBoundary(), fileField, file, mimeType, fileContent, true, true);
263
        checkContentLength(connection, expectedFormBody.length);        
264
        checkArraysHaveSameContent(expectedFormBody, connection.getOutputStreamContent());
265
        connection.disconnect();
266
    }
267
268
    /*
269
     * Test method for 'org.apache.jmeter.protocol.http.sampler.PostWriter.sendPostData(URLConnection, HTTPSampler)'
270
     * This method test sending only a formdata, as a multipart/form-data request.
271
     */
272
    public void testSendFormData_Multipart() throws IOException {
273
        String titleField = "title";
274
        String titleValue = "mytitle";
275
        String descriptionField = "description";
276
        String descriptionValue = "mydescription";
277
        setupFormData(sampler, titleValue, descriptionValue);
278
        // Tell sampler to do multipart, even if we have no files to upload
279
        sampler.setDoMultipartPost(true);
280
281
        // Test sending data with default encoding
282
        String contentEncoding = "";
283
        sampler.setContentEncoding(contentEncoding);        
284
        postWriter.setHeaders(connection, sampler);
285
        postWriter.sendPostData(connection, sampler);
286
287
        checkContentTypeMultipart(connection, postWriter.getBoundary());
288
        byte[] expectedFormBody = createExpectedFormdataOutput(postWriter.getBoundary(), "iso-8859-1", titleField, titleValue, descriptionField, descriptionValue, true, true);
289
        checkContentLength(connection, expectedFormBody.length);
290
        checkArraysHaveSameContent(expectedFormBody, connection.getOutputStreamContent());
291
        connection.disconnect();
292
293
        // Test sending data as ISO-8859-1
294
        establishConnection();
295
        contentEncoding = "ISO-8859-1";
296
        sampler.setContentEncoding(contentEncoding);        
297
        postWriter.setHeaders(connection, sampler);
298
        postWriter.sendPostData(connection, sampler);
299
300
        checkContentTypeMultipart(connection, postWriter.getBoundary());
301
        expectedFormBody = createExpectedFormdataOutput(postWriter.getBoundary(), contentEncoding, titleField, titleValue, descriptionField, descriptionValue, true, true);
302
        checkContentLength(connection, expectedFormBody.length);
303
        checkArraysHaveSameContent(expectedFormBody, connection.getOutputStreamContent());
304
        connection.disconnect();
305
        
306
        // Test sending data as ISO-8859-1, with values that need to be urlencoded
307
        establishConnection();
308
        titleValue = "mytitle+123 456&yes";
309
        descriptionValue = "mydescription and some spaces";
310
        contentEncoding = "ISO-8859-1";
311
        sampler.setContentEncoding(contentEncoding);        
312
        setupFormData(sampler, titleValue, descriptionValue);
313
        postWriter.setHeaders(connection, sampler);
314
        postWriter.sendPostData(connection, sampler);
315
316
        checkContentTypeMultipart(connection, postWriter.getBoundary());
317
        expectedFormBody = createExpectedFormdataOutput(postWriter.getBoundary(), contentEncoding, titleField, titleValue, descriptionField, descriptionValue, true, true);
318
        checkContentLength(connection, expectedFormBody.length);
319
        checkArraysHaveSameContent(expectedFormBody, connection.getOutputStreamContent());
320
        connection.disconnect();
321
        
322
        // Test sending data as UTF-8
323
        establishConnection();
324
        titleValue = "mytitle\u0153\u20a1\u0115\u00c5";
325
        descriptionValue = "mydescription\u0153\u20a1\u0115\u00c5";
326
        contentEncoding = "UTF-8";
327
        sampler.setContentEncoding(contentEncoding);        
328
        setupFormData(sampler, titleValue, descriptionValue);
329
        postWriter.setHeaders(connection, sampler);
330
        postWriter.sendPostData(connection, sampler);
331
332
        checkContentTypeMultipart(connection, postWriter.getBoundary());
333
        expectedFormBody = createExpectedFormdataOutput(postWriter.getBoundary(), contentEncoding, titleField, titleValue, descriptionField, descriptionValue, true, true);
334
        checkContentLength(connection, expectedFormBody.length);
335
        checkArraysHaveSameContent(expectedFormBody, connection.getOutputStreamContent());
336
        connection.disconnect();
337
338
        // Test sending data as UTF-8, with values that would have been urlencoded
339
        // if it was not sent as multipart
340
        establishConnection();
341
        titleValue = "mytitle\u0153+\u20a1 \u0115&yes\u00c5";
342
        descriptionValue = "mydescription \u0153 \u20a1 \u0115 \u00c5";
343
        contentEncoding = "UTF-8";
344
        sampler.setContentEncoding(contentEncoding);        
345
        setupFormData(sampler, titleValue, descriptionValue);
346
        postWriter.setHeaders(connection, sampler);
347
        postWriter.sendPostData(connection, sampler);
348
349
        checkContentTypeMultipart(connection, postWriter.getBoundary());
350
        expectedFormBody = createExpectedFormdataOutput(postWriter.getBoundary(), contentEncoding, titleField, titleValue, descriptionField, descriptionValue, true, true);
351
        checkContentLength(connection, expectedFormBody.length);
352
        checkArraysHaveSameContent(expectedFormBody, connection.getOutputStreamContent());
353
        connection.disconnect();
354
    }
355
    
356
    /*
357
     * Test method for 'org.apache.jmeter.protocol.http.sampler.PostWriter.sendPostData(URLConnection, HTTPSampler)'
358
     * This method test sending only a formdata, as urlencoded data
359
     */
360
    public void testSendFormData_Urlencoded() throws IOException {
361
        String titleValue = "mytitle";
362
        String descriptionValue = "mydescription";
363
        setupFormData(sampler, titleValue, descriptionValue);
364
365
        // Test sending data with default encoding
366
        String contentEncoding = "";
367
        sampler.setContentEncoding(contentEncoding);        
368
        postWriter.setHeaders(connection, sampler);
369
        postWriter.sendPostData(connection, sampler);
370
        
371
        checkContentTypeUrlEncoded(connection);
372
        byte[] expectedUrl = new String("title=" + titleValue + "&description=" + descriptionValue).getBytes("US-ASCII");        
373
        checkContentLength(connection, expectedUrl.length);
374
        checkArraysHaveSameContent(expectedUrl, connection.getOutputStreamContent());
375
        assertEquals(
376
                URLDecoder.decode(new String(expectedUrl, "US-ASCII"), "ISO-8859-1"), 
377
                URLDecoder.decode(new String(connection.getOutputStreamContent(), "US-ASCII"), "ISO-8859-1")); 
378
        connection.disconnect();
379
380
        // Test sending data as ISO-8859-1
381
        establishConnection();
382
        contentEncoding = "ISO-8859-1";
383
        sampler.setContentEncoding(contentEncoding);        
384
        postWriter.setHeaders(connection, sampler);
385
        postWriter.sendPostData(connection, sampler);
386
        
387
        checkContentTypeUrlEncoded(connection);
388
        expectedUrl = new String("title=" + titleValue + "&description=" + descriptionValue).getBytes("US-ASCII");
389
        checkContentLength(connection, expectedUrl.length);
390
        checkArraysHaveSameContent(expectedUrl, connection.getOutputStreamContent());
391
        assertEquals(
392
                URLDecoder.decode(new String(expectedUrl, "US-ASCII"), contentEncoding), 
393
                URLDecoder.decode(new String(connection.getOutputStreamContent(), "US-ASCII"), contentEncoding)); 
394
        connection.disconnect();
395
        
396
        // Test sending data as ISO-8859-1, with values that need to be urlencoded
397
        establishConnection();
398
        titleValue = "mytitle+123 456&yes";
399
        descriptionValue = "mydescription and some spaces";
400
        contentEncoding = "ISO-8859-1";
401
        sampler.setContentEncoding(contentEncoding);        
402
        setupFormData(sampler, titleValue, descriptionValue);
403
        postWriter.setHeaders(connection, sampler);
404
        postWriter.sendPostData(connection, sampler);
405
        
406
        checkContentTypeUrlEncoded(connection);
407
        String expectedString = "title=" + URLEncoder.encode(titleValue, contentEncoding) + "&description=" + URLEncoder.encode(descriptionValue, contentEncoding);
408
        expectedUrl = expectedString.getBytes(contentEncoding);
409
        checkContentLength(connection, expectedUrl.length);
410
        checkArraysHaveSameContent(expectedUrl, connection.getOutputStreamContent());
411
        assertEquals(
412
                URLDecoder.decode(new String(expectedUrl, "US-ASCII"), contentEncoding), 
413
                URLDecoder.decode(new String(connection.getOutputStreamContent(), "US-ASCII"), contentEncoding)); 
414
        String unencodedString = "title=" + titleValue + "&description=" + descriptionValue;
415
        byte[] unexpectedUrl = unencodedString.getBytes("UTF-8");
416
        checkArraysHaveDifferentContent(unexpectedUrl, connection.getOutputStreamContent());
417
        connection.disconnect();
418
        
419
        // Test sending data as UTF-8
420
        establishConnection();
421
        titleValue = "mytitle\u0153\u20a1\u0115\u00c5";
422
        descriptionValue = "mydescription\u0153\u20a1\u0115\u00c5";
423
        contentEncoding = "UTF-8";
424
        sampler.setContentEncoding(contentEncoding);        
425
        setupFormData(sampler, titleValue, descriptionValue);
426
        postWriter.setHeaders(connection, sampler);
427
        postWriter.sendPostData(connection, sampler);
428
        
429
        checkContentTypeUrlEncoded(connection);
430
        expectedString = "title=" + URLEncoder.encode(titleValue, contentEncoding) + "&description=" + URLEncoder.encode(descriptionValue, contentEncoding);
431
        expectedUrl = expectedString.getBytes("US-ASCII");
432
        checkContentLength(connection, expectedUrl.length);
433
        checkArraysHaveSameContent(expectedUrl, connection.getOutputStreamContent());
434
        assertEquals(
435
                URLDecoder.decode(new String(expectedUrl, "US-ASCII"), contentEncoding), 
436
                URLDecoder.decode(new String(connection.getOutputStreamContent(), "US-ASCII"), contentEncoding)); 
437
        connection.disconnect();
438
439
        // Test sending data as UTF-8, with values that needs to be urlencoded
440
        establishConnection();
441
        titleValue = "mytitle\u0153+\u20a1 \u0115&yes\u00c5";
442
        descriptionValue = "mydescription \u0153 \u20a1 \u0115 \u00c5";
443
        contentEncoding = "UTF-8";
444
        sampler.setContentEncoding(contentEncoding);        
445
        setupFormData(sampler, titleValue, descriptionValue);
446
        postWriter.setHeaders(connection, sampler);
447
        postWriter.sendPostData(connection, sampler);
448
449
        checkContentTypeUrlEncoded(connection);
450
        expectedString = "title=" + URLEncoder.encode(titleValue, "UTF-8") + "&description=" + URLEncoder.encode(descriptionValue, "UTF-8");
451
        expectedUrl = expectedString.getBytes("US-ASCII");
452
        checkContentLength(connection, expectedUrl.length);
453
        checkArraysHaveSameContent(expectedUrl, connection.getOutputStreamContent());
454
        assertEquals(
455
                URLDecoder.decode(new String(expectedUrl, "US-ASCII"), contentEncoding), 
456
                URLDecoder.decode(new String(connection.getOutputStreamContent(), "US-ASCII"), contentEncoding)); 
457
        unencodedString = "title=" + titleValue + "&description=" + descriptionValue;
458
        unexpectedUrl = unencodedString.getBytes("US-ASCII");
459
        checkArraysHaveDifferentContent(unexpectedUrl, connection.getOutputStreamContent());
460
        connection.disconnect();
461
        
462
        // Test sending parameters which are urlencoded beforehand
463
        // The values must be URL encoded with UTF-8 encoding, because that
464
        // is what the HTTPArgument assumes
465
        // %C3%85 in UTF-8 is the same as %C5 in ISO-8859-1, which is the same as &Aring;
466
        titleValue = "mytitle%20and%20space%2Ftest%C3%85";
467
        descriptionValue = "mydescription+and+plus+as+space%2Ftest%C3%85";
468
        setupFormData(sampler, true, titleValue, descriptionValue);
469
470
        // Test sending data with default encoding
471
        establishConnection();
472
        contentEncoding = "";
473
        sampler.setContentEncoding(contentEncoding);        
474
        postWriter.setHeaders(connection, sampler);
475
        postWriter.sendPostData(connection, sampler);
476
        
477
        checkContentTypeUrlEncoded(connection);
478
        expectedUrl = new String("title=" + titleValue.replaceAll("%20", "+").replaceAll("%C3%85", "%C5") + "&description=" + descriptionValue.replaceAll("%C3%85", "%C5")).getBytes("US-ASCII");
479
        checkContentLength(connection, expectedUrl.length);
480
        checkArraysHaveSameContent(expectedUrl, connection.getOutputStreamContent());
481
        assertEquals(
482
                URLDecoder.decode(new String(expectedUrl, "US-ASCII"), "ISO-8859-1"), // HTTPSampler uses ISO-8859-1 as default encoding
483
                URLDecoder.decode(new String(connection.getOutputStreamContent(), "US-ASCII"), "ISO-8859-1")); // HTTPSampler uses ISO-8859-1 as default encoding
484
        connection.disconnect();
485
486
        // Test sending data as ISO-8859-1
487
        establishConnection();
488
        contentEncoding = "ISO-8859-1";
489
        sampler.setContentEncoding(contentEncoding);        
490
        postWriter.setHeaders(connection, sampler);
491
        postWriter.sendPostData(connection, sampler);
492
        
493
        checkContentTypeUrlEncoded(connection);
494
        expectedUrl = new String("title=" + titleValue.replaceAll("%20", "+").replaceAll("%C3%85", "%C5") + "&description=" + descriptionValue.replaceAll("%C3%85", "%C5")).getBytes("US-ASCII");
495
        checkContentLength(connection, expectedUrl.length);
496
        checkArraysHaveSameContent(expectedUrl, connection.getOutputStreamContent());
497
        assertEquals(
498
                URLDecoder.decode(new String(expectedUrl, "US-ASCII"), contentEncoding), 
499
                URLDecoder.decode(new String(connection.getOutputStreamContent(), "US-ASCII"), contentEncoding)); 
500
        connection.disconnect();
501
502
        // Test sending data as UTF-8
503
        establishConnection();
504
        contentEncoding = "UTF-8";
505
        sampler.setContentEncoding(contentEncoding);        
506
        postWriter.setHeaders(connection, sampler);
507
        postWriter.sendPostData(connection, sampler);
508
        
509
        checkContentTypeUrlEncoded(connection);
510
        expectedUrl = new String("title=" + titleValue.replaceAll("%20", "+") + "&description=" + descriptionValue).getBytes("US-ASCII");
511
        checkContentLength(connection, expectedUrl.length);
512
        checkArraysHaveSameContent(expectedUrl, connection.getOutputStreamContent());
513
        assertEquals(
514
                URLDecoder.decode(new String(expectedUrl, "US-ASCII"), contentEncoding), 
515
                URLDecoder.decode(new String(connection.getOutputStreamContent(), "US-ASCII"), contentEncoding)); 
516
        connection.disconnect();
517
    }
518
519
    /*
89
     * Test method for 'org.apache.jmeter.protocol.http.sampler.PostWriter.setHeaders(URLConnection, HTTPSampler)'
520
     * Test method for 'org.apache.jmeter.protocol.http.sampler.PostWriter.setHeaders(URLConnection, HTTPSampler)'
90
     */
521
     */
91
    public void testSetHeaders() throws IOException {
522
    public void testSetHeaders() throws IOException {
92
        setupFilename(sampler);
523
        setupFilepart(sampler);
93
        setupCommons(sampler);
524
        setupFormData(sampler);
94
        
525
        
95
        PostWriter.setHeaders(connection, sampler);
526
        postWriter.setHeaders(connection, sampler);
96
        
527
        checkContentTypeMultipart(connection, postWriter.getBoundary());
97
        assertEquals("multipart/form-data; boundary=" + PostWriter.BOUNDARY, connection.getRequestProperty("Content-Type"));
98
    }
528
    }
99
529
100
    /*
530
    /*
Lines 102-113 Link Here
102
     */
532
     */
103
    public void testSetHeaders_NoFilename() throws IOException {
533
    public void testSetHeaders_NoFilename() throws IOException {
104
        setupNoFilename(sampler);
534
        setupNoFilename(sampler);
105
        setupCommons(sampler);
535
        setupFormData(sampler);
106
        
536
        
107
        PostWriter.setHeaders(connection, sampler);
537
        postWriter.setHeaders(connection, sampler);
108
        
538
        checkContentTypeUrlEncoded(connection);
109
        assertEquals(HTTPSamplerBase.APPLICATION_X_WWW_FORM_URLENCODED, connection.getRequestProperty("Content-Type"));
539
        checkContentLength(connection, "title=mytitle&description=mydescription".length());
110
        assertEquals("39", connection.getRequestProperty("Content-Length"));
111
    }
540
    }
112
541
113
    /**
542
    /**
Lines 117-212 Link Here
117
     * @throws IOException
546
     * @throws IOException
118
     */
547
     */
119
    private void setupNoFilename(HTTPSampler httpSampler) {
548
    private void setupNoFilename(HTTPSampler httpSampler) {
120
        httpSampler.setFilename("");
549
        setupFilepart(sampler, "upload", null, "application/octet-stream");
121
        httpSampler.setMimetype("application/octet-stream");
122
    }
550
    }
123
551
124
    /**
552
    /**
125
     * setup commons parts of HTTPSampler with a filename.
553
     * Setup the filepart with default values
126
     * 
554
     * 
127
     * @param httpSampler
555
     * @param httpSampler
128
     * @throws IOException
129
     */
556
     */
130
    private void setupFilename(HTTPSampler httpSampler) {
557
    private void setupFilepart(HTTPSampler httpSampler) {
131
        // httpSampler.setFilename("test/src/org/apache/jmeter/protocol/http/sampler/foo.txt");
558
        setupFilepart(sampler, "upload", temporaryFile, "text/plain");
132
        httpSampler.setFilename(temporaryFile.getAbsolutePath());
133
        httpSampler.setMimetype("text/plain");
134
    }
559
    }
135
560
136
    /**
561
    /**
137
     * setup commons parts of HTTPSampler form test* methods.
562
     * Setup the filepart with specified values
138
     * 
563
     * 
139
     * @param httpSampler
564
     * @param httpSampler
140
     * @throws IOException
141
     */
565
     */
142
    private void setupCommons(HTTPSampler httpSampler) {
566
    private void setupFilepart(HTTPSampler httpSampler, String fileField, File file, String mimeType) {
143
        httpSampler.setFileField("upload");
567
        httpSampler.setFileField(fileField);
568
        if(file != null) {
569
            httpSampler.setFilename(file.getAbsolutePath());
570
        }
571
        else {
572
            httpSampler.setFilename("");
573
        }
574
        httpSampler.setMimetype(mimeType);
575
    }
576
577
    /**
578
     * Setup the form data with default values
579
     * 
580
     * @param httpSampler
581
     */
582
    private void setupFormData(HTTPSampler httpSampler) {
583
        setupFormData(httpSampler, "mytitle", "mydescription");
584
    }
585
586
    /**
587
     * Setup the form data with specified values
588
     * 
589
     * @param httpSampler
590
     */
591
    private void setupFormData(HTTPSampler httpSampler, String titleValue, String descriptionValue) {
592
        setupFormData(sampler, false, titleValue, descriptionValue);
593
    }
594
595
    /**
596
     * Setup the form data with specified values
597
     * 
598
     * @param httpSampler
599
     */
600
    private void setupFormData(HTTPSampler httpSampler, boolean isEncoded, String titleValue, String descriptionValue) {
144
        Arguments args = new Arguments();
601
        Arguments args = new Arguments();
145
        args.addArgument(new HTTPArgument("title", "mytitle"));
602
        HTTPArgument argument1 = new HTTPArgument("title", titleValue, isEncoded);
146
        args.addArgument(new HTTPArgument("description", "mydescription"));
603
        HTTPArgument argument2 = new HTTPArgument("description", descriptionValue, isEncoded);
604
        args.addArgument(argument1);
605
        args.addArgument(argument2);
147
        httpSampler.setArguments(args);
606
        httpSampler.setArguments(args);
148
    }
607
    }
149
    
608
    
609
    private void establishConnection() throws MalformedURLException { 
610
        connection = new StubURLConnection("http://fake_url/test");
611
        postWriter = new PostWriter();
612
    }
613
    
150
    /**
614
    /**
151
     * Create the expected output with CRLF. 
615
     * Create the expected output post body for form data and file multiparts
616
     * with default values for field names
152
     */
617
     */
153
    private OutputStream createExpectedOutputStream() throws IOException {
618
    private byte[] createExpectedOutput(
154
        /*
619
            String boundaryString,
155
        -----------------------------7d159c1302d0y0
620
            String contentEncoding,
156
        Content-Disposition: form-data; name="title"
621
            String titleValue,
622
            String descriptionValue,
623
            byte[] fileContent) throws IOException {
624
        return createExpectedOutput(boundaryString, contentEncoding, "title", titleValue, "description", descriptionValue, "upload", fileContent);
625
    }
157
626
158
        mytitle
627
    /**
159
        -----------------------------7d159c1302d0y0
628
     * Create the expected output post body for form data and file multiparts
160
        Content-Disposition: form-data; name="description"
629
     * with specified values
630
     */
631
    private byte[] createExpectedOutput(
632
            String boundaryString,
633
            String contentEncoding,
634
            String titleField,
635
            String titleValue,
636
            String descriptionField,
637
            String descriptionValue,
638
            String fileField,
639
            byte[] fileContent) throws IOException {
640
        // Create the multiparts
641
        byte[] formdataMultipart = createExpectedFormdataOutput(boundaryString, contentEncoding, titleField, titleValue, descriptionField, descriptionValue, true, false);
642
        byte[] fileMultipart = createExpectedFilepartOutput(boundaryString, fileField, temporaryFile, "text/plain", fileContent, false, true);
643
        
644
        // Join the two multiparts
645
        ByteArrayOutputStream output = new ByteArrayOutputStream();
646
        output.write(formdataMultipart);
647
        output.write(fileMultipart);
648
        
649
        output.flush();
650
        output.close();
651
        
652
        return output.toByteArray();
653
    }
161
654
162
        mydescription
655
    /**
163
        -----------------------------7d159c1302d0y0
656
     * Create the expected output multipart/form-data, with only form data,
164
        Content-Disposition: form-data; name="upload"; filename="test/src/org/apache/jmeter/protocol/http/sampler/foo.txt"
657
     * and no file multipart
165
        Content-Type: plain/text
658
     * 
166
659
     * @param lastMultipart true if this is the last multipart in the request
167
        foo content
660
     */
168
        -----------------------------7d159c1302d0y0--
661
    private byte[] createExpectedFormdataOutput(
169
        */
662
            String boundaryString,
170
663
            String contentEncoding,
171
        final OutputStream output = new ByteArrayOutputStream();
664
            String titleField,
172
        output.write("-----------------------------7d159c1302d0y0".getBytes());
665
            String titleValue,
666
            String descriptionField,
667
            String descriptionValue,
668
            boolean firstMultipart,
669
            boolean lastMultipart) throws IOException {
670
        // The encoding used for http headers and control information
671
        final String httpEncoding = "ISO-8859-1";
672
        final byte[] DASH_DASH = new String("--").getBytes(httpEncoding);
673
        
674
        final ByteArrayOutputStream output = new ByteArrayOutputStream();
675
        if(firstMultipart) {
676
            output.write(DASH_DASH);
677
            output.write(boundaryString.getBytes(httpEncoding));
678
            output.write(CRLF);
679
        }
680
        output.write("Content-Disposition: form-data; name=\"".getBytes(httpEncoding));
681
        output.write(titleField.getBytes(httpEncoding));
682
        output.write("\"".getBytes(httpEncoding));
173
        output.write(CRLF);
683
        output.write(CRLF);
174
        output.write("Content-Disposition: form-data; name=\"title\"".getBytes());
684
        output.write("Content-Type: text/plain".getBytes(httpEncoding));
685
        if(contentEncoding != null) {
686
            output.write("; charset=".getBytes(httpEncoding));
687
            output.write(contentEncoding.getBytes(httpEncoding));
688
        }
175
        output.write(CRLF);
689
        output.write(CRLF);
690
        output.write("Content-Transfer-Encoding: 8bit".getBytes(httpEncoding));
176
        output.write(CRLF);
691
        output.write(CRLF);
177
        output.write("mytitle".getBytes());
178
        output.write(CRLF);
692
        output.write(CRLF);
179
        output.write("-----------------------------7d159c1302d0y0".getBytes());
693
        if(contentEncoding != null) {
694
            output.write(titleValue.getBytes(contentEncoding));
695
        }
696
        else {
697
            output.write(titleValue.getBytes());
698
        }
180
        output.write(CRLF);
699
        output.write(CRLF);
181
        output.write("Content-Disposition: form-data; name=\"description\"".getBytes());
700
        output.write(DASH_DASH);
701
        output.write(boundaryString.getBytes(httpEncoding));
182
        output.write(CRLF);
702
        output.write(CRLF);
703
        output.write("Content-Disposition: form-data; name=\"".getBytes(httpEncoding));
704
        output.write(descriptionField.getBytes(httpEncoding));
705
        output.write("\"".getBytes(httpEncoding));
183
        output.write(CRLF);
706
        output.write(CRLF);
184
        output.write("mydescription".getBytes());
707
        output.write("Content-Type: text/plain".getBytes(httpEncoding));
708
        if(contentEncoding != null) {
709
            output.write("; charset=".getBytes(httpEncoding));
710
            output.write(contentEncoding.getBytes(httpEncoding));
711
        }
185
        output.write(CRLF);
712
        output.write(CRLF);
186
        output.write("-----------------------------7d159c1302d0y0".getBytes());
713
        output.write("Content-Transfer-Encoding: 8bit".getBytes(httpEncoding));
187
        output.write(CRLF);
714
        output.write(CRLF);
715
        output.write(CRLF);
716
        if(contentEncoding != null) {
717
            output.write(descriptionValue.getBytes(contentEncoding));
718
        }
719
        else {
720
            output.write(descriptionValue.getBytes());
721
        }
722
        output.write(CRLF);
723
        output.write(DASH_DASH);
724
        output.write(boundaryString.getBytes(httpEncoding));
725
        if(lastMultipart) {
726
            output.write(DASH_DASH);
727
        }
728
        output.write(CRLF);
729
                
730
        output.flush();
731
        output.close();
732
733
        return output.toByteArray();
734
    }
735
    
736
    /**
737
     * Create the expected file multipart
738
     * 
739
     * @param lastMultipart true if this is the last multipart in the request
740
     */
741
    private byte[] createExpectedFilepartOutput(
742
            String boundaryString,
743
            String fileField,
744
            File file,
745
            String mimeType,
746
            byte[] fileContent,
747
            boolean firstMultipart,
748
            boolean lastMultipart) throws IOException {
749
        // The encoding used for http headers and control information
750
        final String httpEncoding = "ISO-8859-1";
751
        final byte[] DASH_DASH = new String("--").getBytes(httpEncoding);
752
        
753
        final ByteArrayOutputStream output = new ByteArrayOutputStream();
754
        if(firstMultipart) {
755
            output.write(DASH_DASH);
756
            output.write(boundaryString.getBytes(httpEncoding));
757
            output.write(CRLF);
758
        }
188
        // replace all backslash with double backslash
759
        // replace all backslash with double backslash
189
        String filename = temporaryFile.getAbsolutePath().replaceAll("\\\\","\\\\\\\\");
760
        String filename = file.getAbsolutePath().replaceAll("\\\\","\\\\\\\\");
190
        output.write(("Content-Disposition: form-data; name=\"upload\"; filename=\"" + filename + "\"").getBytes());
761
        output.write("Content-Disposition: form-data; name=\"".getBytes(httpEncoding));
762
        output.write(fileField.getBytes(httpEncoding));
763
        output.write(("\"; filename=\"" + filename + "\"").getBytes(httpEncoding));
191
        output.write(CRLF);
764
        output.write(CRLF);
192
        output.write("Content-Type: text/plain".getBytes());
765
        output.write("Content-Type: ".getBytes(httpEncoding));
766
        output.write(mimeType.getBytes(httpEncoding));
193
        output.write(CRLF);
767
        output.write(CRLF);
768
        output.write("Content-Transfer-Encoding: 8bit".getBytes(httpEncoding));
769
        output.write(CRLF);        
194
        output.write(CRLF);
770
        output.write(CRLF);
195
        output.write("foo content".getBytes());
771
        output.write(fileContent);
196
        output.write(CRLF);
772
        output.write(CRLF);
197
        output.write("-----------------------------7d159c1302d0y0--".getBytes());
773
        output.write(DASH_DASH);
774
        output.write(boundaryString.getBytes(httpEncoding));
775
        if(lastMultipart) {
776
            output.write(DASH_DASH);
777
        }
198
        output.write(CRLF);
778
        output.write(CRLF);
779
        
199
        output.flush();
780
        output.flush();
200
        output.close();
781
        output.close();
201
        return output;
782
783
        return output.toByteArray();
202
    }
784
    }
203
785
204
    /**
786
    /**
787
     * Check that the the two byte arrays have identical content
788
     * 
789
     * @param expected
790
     * @param actual
791
     */
792
    private void checkArraysHaveSameContent(byte[] expected, byte[] actual) {
793
        if(expected != null && actual != null) {
794
            if(expected.length != actual.length) {
795
                fail("arrays have different length, expected is " + expected.length + ", actual is " + actual.length);
796
            }
797
            else {
798
                for(int i = 0; i < expected.length; i++) {
799
                    if(expected[i] != actual[i]) {
800
                        fail("byte at position " + i + " is different, expected is " + expected[i] + ", actual is " + actual[i]);
801
                    }
802
                }
803
            }
804
        }
805
        else {
806
            fail("expected or actual byte arrays were null");
807
        }
808
    }
809
810
    /**
811
     * Check that the the two byte arrays different content
812
     * 
813
     * @param expected
814
     * @param actual
815
     */
816
    private void checkArraysHaveDifferentContent(byte[] expected, byte[] actual) {
817
        if(expected != null && actual != null) {
818
            if(expected.length == actual.length) {
819
                boolean allSame = true;
820
                for(int i = 0; i < expected.length; i++) {
821
                    if(expected[i] != actual[i]) {
822
                        allSame = false;
823
                        break;
824
                    }
825
                }
826
                if(allSame) {
827
                    fail("all bytes were equal");
828
                }
829
            }
830
        }
831
        else {
832
            fail("expected or actual byte arrays were null");
833
        }
834
    }
835
    
836
    private void checkContentTypeMultipart(HttpURLConnection connection, String boundaryString) {
837
        assertEquals("multipart/form-data; boundary=" + boundaryString, connection.getRequestProperty("Content-Type"));
838
    }
839
840
    private void checkContentTypeUrlEncoded(HttpURLConnection connection) {
841
        assertEquals(HTTPSamplerBase.APPLICATION_X_WWW_FORM_URLENCODED, connection.getRequestProperty("Content-Type"));
842
    }
843
844
    private void checkContentLength(HttpURLConnection connection, int length) {
845
        assertEquals(Integer.toString(length), connection.getRequestProperty("Content-Length"));
846
    }
847
848
    /**
205
     * Mock an HttpURLConnection.
849
     * Mock an HttpURLConnection.
206
     * extends HttpURLConnection instead of just URLConnection because there is a cast in PostWriter.
850
     * extends HttpURLConnection instead of just URLConnection because there is a cast in PostWriter.
207
     */
851
     */
208
    private static class StubURLConnection extends HttpURLConnection {
852
    private static class StubURLConnection extends HttpURLConnection {
209
        private OutputStream output = new ByteArrayOutputStream();
853
        private ByteArrayOutputStream output = new ByteArrayOutputStream();
210
        private Map properties = new HashMap();
854
        private Map properties = new HashMap();
211
        
855
        
212
        public StubURLConnection(String url) throws MalformedURLException {
856
        public StubURLConnection(String url) throws MalformedURLException {
Lines 234-238 Link Here
234
        public void setRequestProperty(String key, String value) {
878
        public void setRequestProperty(String key, String value) {
235
            properties.put(key, value);
879
            properties.put(key, value);
236
        }
880
        }
881
        
882
        public byte[] getOutputStreamContent() {
883
            return output.toByteArray();
884
        }
237
    }
885
    }
238
}
886
}

Return to bug 27780