001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.commons.fileupload;
018    
019    import java.io.ByteArrayOutputStream;
020    import java.io.IOException;
021    import java.io.InputStream;
022    
023    import org.apache.commons.fileupload.ProgressListener;
024    import org.apache.commons.fileupload.servlet.ServletFileUpload;
025    
026    
027    /** Tests the progress listener.
028     */
029    public class ProgressListenerTest extends FileUploadTestCase {
030            private class ProgressListenerImpl implements ProgressListener {
031                    private final long expectedContentLength;
032                    private final int expectedItems;
033                    private Long bytesRead;
034                    private Integer items;
035                    ProgressListenerImpl(long pContentLength, int pItems) {
036                            expectedContentLength = pContentLength;
037                            expectedItems = pItems;
038                    }
039                    public void update(long pBytesRead, long pContentLength, int pItems) {
040                            assertTrue(pBytesRead >= 0  &&  pBytesRead <= expectedContentLength);
041                            assertTrue(pContentLength == -1  ||  pContentLength == expectedContentLength);
042                            assertTrue(pItems >= 0  &&  pItems <= expectedItems);
043    
044                            assertTrue(bytesRead == null  ||  pBytesRead >= bytesRead.longValue());
045                            bytesRead = new Long(pBytesRead);
046                            assertTrue(items == null  ||  pItems >= items.intValue());
047                            items = new Integer(pItems);
048                    }
049                    void checkFinished(){
050                            assertEquals(expectedContentLength, bytesRead.longValue());
051                            assertEquals(expectedItems, items.intValue());
052                    }
053            }
054    
055            /**
056             * Parse a very long file upload by using a progress listener.
057             */
058            public void testProgressListener() throws Exception {
059                    final int NUM_ITEMS = 512;
060            ByteArrayOutputStream baos = new ByteArrayOutputStream();
061            for (int i = 0;  i < NUM_ITEMS;  i++) {
062                String header = "-----1234\r\n"
063                    + "Content-Disposition: form-data; name=\"field" + (i+1) + "\"\r\n"
064                    + "\r\n";
065                baos.write(header.getBytes("US-ASCII"));
066                for (int j = 0;  j < 16384+i;  j++) {
067                    baos.write((byte) j);
068                }
069                baos.write("\r\n".getBytes("US-ASCII"));
070            }
071            baos.write("-----1234--\r\n".getBytes("US-ASCII"));
072            byte[] contents = baos.toByteArray();
073    
074            MockHttpServletRequest request = new MockHttpServletRequest(contents, "multipart/form-data; boundary=---1234");
075            runTest(NUM_ITEMS, contents.length, request);
076            request = new MockHttpServletRequest(contents, "multipart/form-data; boundary=---1234"){
077                            public int getContentLength() {
078                                    return -1;
079                            }               
080            };
081            runTest(NUM_ITEMS, contents.length, request);
082            }
083    
084            private void runTest(final int NUM_ITEMS, long pContentLength, MockHttpServletRequest request) throws FileUploadException, IOException {
085                    ServletFileUpload upload = new ServletFileUpload();
086            ProgressListenerImpl listener = new ProgressListenerImpl(pContentLength, NUM_ITEMS);
087            upload.setProgressListener(listener);
088            FileItemIterator iter = upload.getItemIterator(request);
089            for (int i = 0;  i < NUM_ITEMS;  i++) {
090                    FileItemStream stream = iter.next();
091                    InputStream istream = stream.openStream();
092                    for (int j = 0;  j < 16384+i;  j++) {
093                        /**
094                     * This used to be
095                     *     assertEquals((byte) j, (byte) istream.read());
096                     * but this seems to trigger a bug in JRockit, so
097                     * we express the same like this:
098                         */
099                    byte b1 = (byte) j;
100                    byte b2 = (byte) istream.read();
101                    if (b1 != b2) {
102                        fail("Expected " + b1 + ", got " + b2);
103                    }
104                    }
105                    assertEquals(-1, istream.read());
106            }
107            assertTrue(!iter.hasNext());
108            listener.checkFinished();
109            }
110    }