    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    }