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

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

Return to bug 27780