Source code: org/apache/http/io/TestChunkCoding.java
1 /*
2 * $HeadURL: https://svn.apache.org/repos/asf/jakarta/httpcomponents/httpcore/tags/4.0-alpha2/src/test/org/apache/http/io/TestChunkCoding.java $
3 * $Revision: 389604 $
4 * $Date: 2006-03-28 23:03:47 +0200 (Tue, 28 Mar 2006) $
5 * ====================================================================
6 *
7 * Copyright 2002-2004 The Apache Software Foundation
8 *
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
12 *
13 * http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 * ====================================================================
21 *
22 * This software consists of voluntary contributions made by many
23 * individuals on behalf of the Apache Software Foundation. For more
24 * information on the Apache Software Foundation, please see
25 * <http://www.apache.org/>.
26 *
27 */
28
29 package org.apache.http.io;
30
31 import java.io.ByteArrayOutputStream;
32 import java.io.IOException;
33 import java.io.InputStream;
34 import java.io.OutputStream;
35
36 import org.apache.http.Header;
37 import org.apache.http.mockup.HttpDataReceiverMockup;
38 import org.apache.http.mockup.HttpDataTransmitterMockup;
39 import org.apache.http.util.EncodingUtils;
40
41 import junit.framework.Test;
42 import junit.framework.TestCase;
43 import junit.framework.TestSuite;
44
45 public class TestChunkCoding extends TestCase {
46
47 private static final String CONTENT_CHARSET = "ISO-8859-1";
48
49 public TestChunkCoding(String testName) {
50 super(testName);
51 }
52
53 // ------------------------------------------------------- TestCase Methods
54
55 public static Test suite() {
56 return new TestSuite(TestChunkCoding.class);
57 }
58
59 // ------------------------------------------------------------------- Main
60 public static void main(String args[]) {
61 String[] testCaseName = { TestChunkCoding.class.getName() };
62 junit.textui.TestRunner.main(testCaseName);
63 }
64
65 public void testConstructors() throws Exception {
66 try {
67 new ChunkedInputStream((HttpDataReceiver)null);
68 fail("IllegalArgumentException should have been thrown");
69 } catch (IllegalArgumentException ex) {
70 // expected
71 }
72 new MalformedChunkCodingException();
73 new MalformedChunkCodingException("");
74 }
75
76 private final static String CHUNKED_INPUT
77 = "10;key=\"value\"\r\n1234567890123456\r\n5\r\n12345\r\n0\r\nFooter1: abcde\r\nFooter2: fghij\r\n";
78
79 private final static String CHUNKED_RESULT
80 = "123456789012345612345";
81
82 // Test for when buffer is larger than chunk size
83 public void testChunkedInputStreamLargeBuffer() throws IOException {
84 ChunkedInputStream in = new ChunkedInputStream(
85 new HttpDataReceiverMockup(
86 EncodingUtils.getBytes(CHUNKED_INPUT, CONTENT_CHARSET)));
87 byte[] buffer = new byte[300];
88 ByteArrayOutputStream out = new ByteArrayOutputStream();
89 int len;
90 while ((len = in.read(buffer)) > 0) {
91 out.write(buffer, 0, len);
92 }
93 assertEquals(-1, in.read(buffer));
94 assertEquals(-1, in.read(buffer));
95
96 in.close();
97
98 String result = EncodingUtils.getString(out.toByteArray(), CONTENT_CHARSET);
99 assertEquals(result, CHUNKED_RESULT);
100
101 Header[] footers = in.getFooters();
102 assertNotNull(footers);
103 assertEquals(2, footers.length);
104 assertEquals("Footer1", footers[0].getName());
105 assertEquals("abcde", footers[0].getValue());
106 assertEquals("Footer2", footers[1].getName());
107 assertEquals("fghij", footers[1].getValue());
108 }
109
110 //Test for when buffer is smaller than chunk size.
111 public void testChunkedInputStreamSmallBuffer() throws IOException {
112 ChunkedInputStream in = new ChunkedInputStream(
113 new HttpDataReceiverMockup(
114 EncodingUtils.getBytes(CHUNKED_INPUT, CONTENT_CHARSET)));
115
116 byte[] buffer = new byte[7];
117 ByteArrayOutputStream out = new ByteArrayOutputStream();
118 int len;
119 while ((len = in.read(buffer)) > 0) {
120 out.write(buffer, 0, len);
121 }
122 assertEquals(-1, in.read(buffer));
123 assertEquals(-1, in.read(buffer));
124
125 in.close();
126
127 EncodingUtils.getString(out.toByteArray(), CONTENT_CHARSET);
128 Header[] footers = in.getFooters();
129 assertNotNull(footers);
130 assertEquals(2, footers.length);
131 assertEquals("Footer1", footers[0].getName());
132 assertEquals("abcde", footers[0].getValue());
133 assertEquals("Footer2", footers[1].getName());
134 assertEquals("fghij", footers[1].getValue());
135 }
136
137 // One byte read
138 public void testChunkedInputStreamOneByteRead() throws IOException {
139 String s = "5\r\n01234\r\n5\r\n56789\r\n0\r\n";
140 ChunkedInputStream in = new ChunkedInputStream(
141 new HttpDataReceiverMockup(
142 EncodingUtils.getBytes(s, CONTENT_CHARSET)));
143 int ch;
144 int i = '0';
145 while ((ch = in.read()) != -1) {
146 assertEquals(i, ch);
147 i++;
148 }
149 assertEquals(-1, in.read());
150 assertEquals(-1, in.read());
151
152 in.close();
153 }
154
155 public void testChunkedInputStreamClose() throws IOException {
156 String s = "5\r\n01234\r\n5\r\n56789\r\n0\r\n";
157 ChunkedInputStream in = new ChunkedInputStream(
158 new HttpDataReceiverMockup(
159 EncodingUtils.getBytes(s, CONTENT_CHARSET)));
160 in.close();
161 in.close();
162 try {
163 in.read();
164 fail("IOException should have been thrown");
165 } catch (IOException ex) {
166 // expected
167 }
168 byte[] tmp = new byte[10];
169 try {
170 in.read(tmp);
171 fail("IOException should have been thrown");
172 } catch (IOException ex) {
173 // expected
174 }
175 try {
176 in.read(tmp, 0, tmp.length);
177 fail("IOException should have been thrown");
178 } catch (IOException ex) {
179 // expected
180 }
181 }
182
183 public void testChunkedOutputStreamClose() throws IOException {
184 ChunkedOutputStream out = new ChunkedOutputStream(
185 new HttpDataTransmitterMockup());
186 out.close();
187 out.close();
188 try {
189 out.write(new byte[] {1,2,3});
190 fail("IOException should have been thrown");
191 } catch (IOException ex) {
192 // expected
193 }
194 try {
195 out.write(1);
196 fail("IOException should have been thrown");
197 } catch (IOException ex) {
198 // expected
199 }
200 }
201
202 // Missing \r\n at the end of the first chunk
203 public void testCorruptChunkedInputStreamMissingCRLF() throws IOException {
204 String s = "5\r\n012345\r\n56789\r\n0\r\n";
205 InputStream in = new ChunkedInputStream(
206 new HttpDataReceiverMockup(
207 EncodingUtils.getBytes(s, CONTENT_CHARSET)));
208 byte[] buffer = new byte[300];
209 ByteArrayOutputStream out = new ByteArrayOutputStream();
210 int len;
211 try {
212 while ((len = in.read(buffer)) > 0) {
213 out.write(buffer, 0, len);
214 }
215 fail("MalformedChunkCodingException should have been thrown");
216 } catch(MalformedChunkCodingException e) {
217 /* expected exception */
218 }
219 }
220
221 // Missing LF
222 public void testCorruptChunkedInputStreamMissingLF() throws IOException {
223 String s = "5\r01234\r\n5\r\n56789\r\n0\r\n";
224 InputStream in = new ChunkedInputStream(
225 new HttpDataReceiverMockup(
226 EncodingUtils.getBytes(s, CONTENT_CHARSET)));
227 try {
228 in.read();
229 fail("MalformedChunkCodingException should have been thrown");
230 } catch(MalformedChunkCodingException e) {
231 /* expected exception */
232 }
233 }
234
235 // Missing closing chunk
236 public void testCorruptChunkedInputStreamNoClosingChunk() throws IOException {
237 InputStream in = new ChunkedInputStream(
238 new HttpDataReceiverMockup(new byte[] {}));
239 try {
240 in.read();
241 fail("MalformedChunkCodingException should have been thrown");
242 } catch(MalformedChunkCodingException e) {
243 /* expected exception */
244 }
245 }
246
247 // Invalid chunk size
248 public void testCorruptChunkedInputStreamInvalidSize() throws IOException {
249 String s = "whatever\r\n01234\r\n5\r\n56789\r\n0\r\n";
250 InputStream in = new ChunkedInputStream(
251 new HttpDataReceiverMockup(
252 EncodingUtils.getBytes(s, CONTENT_CHARSET)));
253 try {
254 in.read();
255 fail("MalformedChunkCodingException should have been thrown");
256 } catch(MalformedChunkCodingException e) {
257 /* expected exception */
258 }
259 }
260
261 // Negative chunk size
262 public void testCorruptChunkedInputStreamNegativeSize() throws IOException {
263 String s = "-5\r\n01234\r\n5\r\n56789\r\n0\r\n";
264 InputStream in = new ChunkedInputStream(
265 new HttpDataReceiverMockup(
266 EncodingUtils.getBytes(s, CONTENT_CHARSET)));
267 try {
268 in.read();
269 fail("MalformedChunkCodingException should have been thrown");
270 } catch(MalformedChunkCodingException e) {
271 /* expected exception */
272 }
273 }
274
275 // Invalid footer
276 public void testCorruptChunkedInputStreamInvalidFooter() throws IOException {
277 String s = "1\r\n0\r\n0\r\nstuff\r\n";
278 InputStream in = new ChunkedInputStream(
279 new HttpDataReceiverMockup(
280 EncodingUtils.getBytes(s, CONTENT_CHARSET)));
281 try {
282 in.read();
283 in.read();
284 fail("MalformedChunkCodingException should have been thrown");
285 } catch(MalformedChunkCodingException e) {
286 /* expected exception */
287 }
288 }
289
290 public void testEmptyChunkedInputStream() throws IOException {
291 String input = "0\r\n";
292 InputStream in = new ChunkedInputStream(
293 new HttpDataReceiverMockup(
294 EncodingUtils.getBytes(input, CONTENT_CHARSET)));
295 byte[] buffer = new byte[300];
296 ByteArrayOutputStream out = new ByteArrayOutputStream();
297 int len;
298 while ((len = in.read(buffer)) > 0) {
299 out.write(buffer, 0, len);
300 }
301 assertEquals(0, out.size());
302 }
303
304 public void testChunkedConsitance() throws IOException {
305 String input = "76126;27823abcd;:q38a-\nkjc\rk%1ad\tkh/asdui\r\njkh+?\\suweb";
306 ByteArrayOutputStream buffer = new ByteArrayOutputStream();
307 OutputStream out = new ChunkedOutputStream(new HttpDataTransmitterMockup(buffer));
308 out.write(EncodingUtils.getBytes(input, CONTENT_CHARSET));
309 out.flush();
310 out.close();
311 out.close();
312 buffer.close();
313 InputStream in = new ChunkedInputStream(
314 new HttpDataReceiverMockup(
315 buffer.toByteArray()));
316
317 byte[] d = new byte[10];
318 ByteArrayOutputStream result = new ByteArrayOutputStream();
319 int len = 0;
320 while ((len = in.read(d)) > 0) {
321 result.write(d, 0, len);
322 }
323
324 String output = EncodingUtils.getString(result.toByteArray(), CONTENT_CHARSET);
325 assertEquals(input, output);
326 }
327
328 public void testChunkedOutputStream() throws IOException {
329 HttpDataTransmitterMockup buffer = new HttpDataTransmitterMockup();
330 ChunkedOutputStream out = new ChunkedOutputStream(buffer, 2);
331 out.write('1');
332 out.write('2');
333 out.write('3');
334 out.write('4');
335 out.finish();
336 out.close();
337
338 byte [] rawdata = buffer.getData();
339
340 assertEquals(19, rawdata.length);
341 assertEquals('2', rawdata[0]);
342 assertEquals('\r', rawdata[1]);
343 assertEquals('\n', rawdata[2]);
344 assertEquals('1', rawdata[3]);
345 assertEquals('2', rawdata[4]);
346 assertEquals('\r', rawdata[5]);
347 assertEquals('\n', rawdata[6]);
348 assertEquals('2', rawdata[7]);
349 assertEquals('\r', rawdata[8]);
350 assertEquals('\n', rawdata[9]);
351 assertEquals('3', rawdata[10]);
352 assertEquals('4', rawdata[11]);
353 assertEquals('\r', rawdata[12]);
354 assertEquals('\n', rawdata[13]);
355 assertEquals('0', rawdata[14]);
356 assertEquals('\r', rawdata[15]);
357 assertEquals('\n', rawdata[16]);
358 assertEquals('\r', rawdata[17]);
359 assertEquals('\n', rawdata[18]);
360 }
361
362 public void testChunkedOutputStreamLargeChunk() throws IOException {
363 HttpDataTransmitterMockup buffer = new HttpDataTransmitterMockup();
364 ChunkedOutputStream out = new ChunkedOutputStream(buffer, 2);
365 out.write(new byte[] {'1', '2', '3', '4'});
366 out.finish();
367 out.close();
368
369 byte [] rawdata = buffer.getData();
370
371 assertEquals(14, rawdata.length);
372 assertEquals('4', rawdata[0]);
373 assertEquals('\r', rawdata[1]);
374 assertEquals('\n', rawdata[2]);
375 assertEquals('1', rawdata[3]);
376 assertEquals('2', rawdata[4]);
377 assertEquals('3', rawdata[5]);
378 assertEquals('4', rawdata[6]);
379 assertEquals('\r', rawdata[7]);
380 assertEquals('\n', rawdata[8]);
381 assertEquals('0', rawdata[9]);
382 assertEquals('\r', rawdata[10]);
383 assertEquals('\n', rawdata[11]);
384 assertEquals('\r', rawdata[12]);
385 assertEquals('\n', rawdata[13]);
386 }
387
388 public void testChunkedOutputStreamSmallChunk() throws IOException {
389 ByteArrayOutputStream buffer = new ByteArrayOutputStream();
390 ChunkedOutputStream out = new ChunkedOutputStream(
391 new HttpDataTransmitterMockup(buffer), 2);
392 out.write('1');
393 out.finish();
394 out.close();
395
396 byte [] rawdata = buffer.toByteArray();
397
398 assertEquals(11, rawdata.length);
399 assertEquals('1', rawdata[0]);
400 assertEquals('\r', rawdata[1]);
401 assertEquals('\n', rawdata[2]);
402 assertEquals('1', rawdata[3]);
403 assertEquals('\r', rawdata[4]);
404 assertEquals('\n', rawdata[5]);
405 assertEquals('0', rawdata[6]);
406 assertEquals('\r', rawdata[7]);
407 assertEquals('\n', rawdata[8]);
408 assertEquals('\r', rawdata[9]);
409 assertEquals('\n', rawdata[10]);
410 }
411
412 }
413