View Javadoc
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  package org.apache.commons.fileupload;
19  
20  import static org.junit.Assert.assertEquals;
21  import static org.junit.Assert.assertTrue;
22  import static org.junit.Assert.fail;
23  
24  import java.io.ByteArrayOutputStream;
25  import java.io.IOException;
26  import java.io.InputStream;
27  
28  import org.apache.commons.fileupload.servlet.ServletFileUpload;
29  import org.junit.Test;
30  
31  /**
32   * Tests the {@link ProgressListener}.
33   */
34  public class ProgressListenerTest {
35  
36      private static class ProgressListenerImpl implements ProgressListener {
37  
38          /** Expected content length. */
39          private final long expectedContentLength;
40  
41          /** Expected item count. */
42          private final int expectedItems;
43  
44          /** Bytes read count. */
45          private Long bytesRead;
46  
47          /** Item count. */
48          private Integer items;
49  
50          ProgressListenerImpl(final long expectedContentLength, final int expectedItems) {
51              this.expectedContentLength = expectedContentLength;
52              this.expectedItems = expectedItems;
53          }
54  
55          void checkFinished() {
56              assertEquals(expectedContentLength, bytesRead.longValue());
57              assertEquals(expectedItems, items.intValue());
58          }
59  
60          @Override
61          public void update(final long actualBytesRead, final long actualContentLength, final int actualItems) {
62              assertTrue(actualBytesRead >= 0 && actualBytesRead <= expectedContentLength);
63              assertTrue(actualContentLength == -1 || actualContentLength == expectedContentLength);
64              assertTrue(actualItems >= 0 && actualItems <= expectedItems);
65              assertTrue(this.bytesRead == null || actualBytesRead >= this.bytesRead.longValue());
66              this.bytesRead = Long.valueOf(actualBytesRead);
67              assertTrue(items == null || actualItems >= items.intValue());
68              this.items = Integer.valueOf(actualItems);
69          }
70      }
71  
72      private void runTest(final int numItems, final long contentLength, final MockHttpServletRequest request) throws FileUploadException, IOException {
73          final ServletFileUpload upload = new ServletFileUpload();
74          final ProgressListenerImpl listener = new ProgressListenerImpl(contentLength, numItems);
75          upload.setProgressListener(listener);
76          final FileItemIterator iter = upload.getItemIterator(request);
77          for (int i = 0; i < numItems; i++) {
78              final FileItemStream stream = iter.next();
79              try (InputStream istream = stream.openStream()) {
80                  final int maxIn = 16384;
81                  for (int j = 0; j < maxIn + i; j++) {
82                      /**
83                       * This used to be assertEquals((byte) j, (byte) istream.read()); but this seems to trigger a bug in JRockit, so we express the same like
84                       * this:
85                       */
86                      final byte b1 = (byte) j;
87                      final byte b2 = (byte) istream.read();
88                      if (b1 != b2) {
89                          fail("Expected " + b1 + ", got " + b2);
90                      }
91                  }
92                  assertEquals(-1, istream.read());
93              }
94          }
95          assertTrue(!iter.hasNext());
96          listener.checkFinished();
97      }
98  
99      /**
100      * Parse a very long file upload by using a progress listener.
101      */
102     @Test
103     public void testProgressListener() throws Exception {
104         final int numItems = 512;
105         final ByteArrayOutputStream baos = new ByteArrayOutputStream();
106         for (int i = 0; i < numItems; i++) {
107             final String header = "-----1234\r\n" + "Content-Disposition: form-data; name=\"field" + (i + 1) + "\"\r\n" + "\r\n";
108             baos.write(header.getBytes("US-ASCII"));
109             final int maxOut = 16384;
110             for (int j = 0; j < maxOut + i; j++) {
111                 baos.write((byte) j);
112             }
113             baos.write("\r\n".getBytes("US-ASCII"));
114         }
115         baos.write("-----1234--\r\n".getBytes("US-ASCII"));
116         final byte[] contents = baos.toByteArray();
117         MockHttpServletRequest request = new MockHttpServletRequest(contents, Constants.CONTENT_TYPE);
118         runTest(numItems, contents.length, request);
119         request = new MockHttpServletRequest(contents, Constants.CONTENT_TYPE) {
120 
121             @Override
122             public int getContentLength() {
123                 return -1;
124             }
125         };
126         runTest(numItems, contents.length, request);
127     }
128 }