com.github.davidcarboni.encryptedfileupload.SizesTest.java Source code

Java tutorial

Introduction

Here is the source code for com.github.davidcarboni.encryptedfileupload.SizesTest.java

Source

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.github.davidcarboni.encryptedfileupload;

import org.apache.commons.fileupload.*;
import org.apache.commons.fileupload.FileUploadBase.FileUploadIOException;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.fileupload.util.Streams;
import org.junit.Test;

import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
import java.util.List;

import static org.junit.Assert.*;

/**
 * Unit test for items with varying sizes.
 *
 * Based on: {@code org.apache.commons.fileupload.SizesTest} 1568663 2014-02-15 18:26:14Z sebb $
 */
public class SizesTest extends FileUploadTestCase {

    /**
     * Runs a test with varying file sizes.
     */
    @Test
    public void testFileUpload() throws IOException, FileUploadException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        int add = 16;
        int num = 0;
        for (int i = 0; i < 16384; i += add) {
            if (++add == 32) {
                add = 16;
            }
            String header = "-----1234\r\n" + "Content-Disposition: form-data; name=\"field" + (num++) + "\"\r\n"
                    + "\r\n";
            baos.write(header.getBytes("US-ASCII"));
            for (int j = 0; j < i; j++) {
                baos.write((byte) j);
            }
            baos.write("\r\n".getBytes("US-ASCII"));
        }
        baos.write("-----1234--\r\n".getBytes("US-ASCII"));

        List<FileItem> fileItems = parseUpload(baos.toByteArray());
        Iterator<FileItem> fileIter = fileItems.iterator();
        add = 16;
        num = 0;
        for (int i = 0; i < 16384; i += add) {
            if (++add == 32) {
                add = 16;
            }
            FileItem item = fileIter.next();
            assertEquals("field" + (num++), item.getFieldName());
            byte[] bytes = item.get();
            assertEquals(i, bytes.length);
            for (int j = 0; j < i; j++) {
                assertEquals((byte) j, bytes[j]);
            }
        }
        assertTrue(!fileIter.hasNext());
    }

    /** Checks, whether limiting the file size works.
     */
    @Test
    public void testFileSizeLimit() throws IOException, FileUploadException {
        final String request = "-----1234\r\n"
                + "Content-Disposition: form-data; name=\"file\"; filename=\"foo.tab\"\r\n"
                + "Content-Type: text/whatever\r\n" + "\r\n" + "This is the content of the file\n" + "\r\n"
                + "-----1234--\r\n";

        ServletFileUpload upload = new ServletFileUpload(new EncryptedFileItemFactory());
        upload.setFileSizeMax(-1);
        HttpServletRequest req = new MockHttpServletRequest(request.getBytes("US-ASCII"), CONTENT_TYPE);
        List<FileItem> fileItems = upload.parseRequest(req);
        assertEquals(1, fileItems.size());
        FileItem item = fileItems.get(0);
        assertEquals("This is the content of the file\n", new String(item.get()));

        upload = new ServletFileUpload(new EncryptedFileItemFactory());
        upload.setFileSizeMax(40);
        req = new MockHttpServletRequest(request.getBytes("US-ASCII"), CONTENT_TYPE);
        fileItems = upload.parseRequest(req);
        assertEquals(1, fileItems.size());
        item = fileItems.get(0);
        assertEquals("This is the content of the file\n", new String(item.get()));

        upload = new ServletFileUpload(new EncryptedFileItemFactory());
        upload.setFileSizeMax(30);
        req = new MockHttpServletRequest(request.getBytes("US-ASCII"), CONTENT_TYPE);
        try {
            upload.parseRequest(req);
            fail("Expected exception.");
        } catch (FileUploadBase.FileSizeLimitExceededException e) {
            assertEquals(30, e.getPermittedSize());
        }
    }

    /** Checks, whether a faked Content-Length header is detected.
     */
    @Test
    public void testFileSizeLimitWithFakedContentLength() throws IOException, FileUploadException {
        final String request = "-----1234\r\n"
                + "Content-Disposition: form-data; name=\"file\"; filename=\"foo.tab\"\r\n"
                + "Content-Type: text/whatever\r\n" + "Content-Length: 10\r\n" + "\r\n"
                + "This is the content of the file\n" + "\r\n" + "-----1234--\r\n";

        ServletFileUpload upload = new ServletFileUpload(new EncryptedFileItemFactory());
        upload.setFileSizeMax(-1);
        HttpServletRequest req = new MockHttpServletRequest(request.getBytes("US-ASCII"), CONTENT_TYPE);
        List<FileItem> fileItems = upload.parseRequest(req);
        assertEquals(1, fileItems.size());
        FileItem item = fileItems.get(0);
        assertEquals("This is the content of the file\n", new String(item.get()));

        upload = new ServletFileUpload(new EncryptedFileItemFactory());
        upload.setFileSizeMax(40);
        req = new MockHttpServletRequest(request.getBytes("US-ASCII"), CONTENT_TYPE);
        fileItems = upload.parseRequest(req);
        assertEquals(1, fileItems.size());
        item = fileItems.get(0);
        assertEquals("This is the content of the file\n", new String(item.get()));

        // provided Content-Length is larger than the FileSizeMax -> handled by ctor
        upload = new ServletFileUpload(new EncryptedFileItemFactory());
        upload.setFileSizeMax(5);
        req = new MockHttpServletRequest(request.getBytes("US-ASCII"), CONTENT_TYPE);
        try {
            upload.parseRequest(req);
            fail("Expected exception.");
        } catch (FileUploadBase.FileSizeLimitExceededException e) {
            assertEquals(5, e.getPermittedSize());
        }

        // provided Content-Length is wrong, actual content is larger -> handled by LimitedInputStream
        upload = new ServletFileUpload(new EncryptedFileItemFactory());
        upload.setFileSizeMax(15);
        req = new MockHttpServletRequest(request.getBytes("US-ASCII"), CONTENT_TYPE);
        try {
            upload.parseRequest(req);
            fail("Expected exception.");
        } catch (FileUploadBase.FileSizeLimitExceededException e) {
            assertEquals(15, e.getPermittedSize());
        }
    }

    /** Checks, whether the maxSize works.
     */
    @Test
    public void testMaxSizeLimit() throws IOException, FileUploadException {
        final String request = "-----1234\r\n"
                + "Content-Disposition: form-data; name=\"file1\"; filename=\"foo1.tab\"\r\n"
                + "Content-Type: text/whatever\r\n" + "Content-Length: 10\r\n" + "\r\n"
                + "This is the content of the file\n" + "\r\n" + "-----1234\r\n"
                + "Content-Disposition: form-data; name=\"file2\"; filename=\"foo2.tab\"\r\n"
                + "Content-Type: text/whatever\r\n" + "\r\n" + "This is the content of the file\n" + "\r\n"
                + "-----1234--\r\n";

        ServletFileUpload upload = new ServletFileUpload(new EncryptedFileItemFactory());
        upload.setFileSizeMax(-1);
        upload.setSizeMax(200);

        MockHttpServletRequest req = new MockHttpServletRequest(request.getBytes("US-ASCII"), CONTENT_TYPE);
        try {
            upload.parseRequest(req);
            fail("Expected exception.");
        } catch (FileUploadBase.SizeLimitExceededException e) {
            assertEquals(200, e.getPermittedSize());
        }

    }

    @Test
    public void testMaxSizeLimitUnknownContentLength() throws IOException, FileUploadException {
        final String request = "-----1234\r\n"
                + "Content-Disposition: form-data; name=\"file1\"; filename=\"foo1.tab\"\r\n"
                + "Content-Type: text/whatever\r\n" + "Content-Length: 10\r\n" + "\r\n"
                + "This is the content of the file\n" + "\r\n" + "-----1234\r\n"
                + "Content-Disposition: form-data; name=\"file2\"; filename=\"foo2.tab\"\r\n"
                + "Content-Type: text/whatever\r\n" + "\r\n" + "This is the content of the file\n" + "\r\n"
                + "-----1234--\r\n";

        ServletFileUpload upload = new ServletFileUpload(new EncryptedFileItemFactory());
        upload.setFileSizeMax(-1);
        upload.setSizeMax(300);

        // the first item should be within the max size limit
        // set the read limit to 10 to simulate a "real" stream
        // otherwise the buffer would be immediately filled

        MockHttpServletRequest req = new MockHttpServletRequest(request.getBytes("US-ASCII"), CONTENT_TYPE);
        req.setContentLength(-1);
        req.setReadLimit(10);

        FileItemIterator it = upload.getItemIterator(req);
        assertTrue(it.hasNext());

        FileItemStream item = it.next();
        assertFalse(item.isFormField());
        assertEquals("file1", item.getFieldName());
        assertEquals("foo1.tab", item.getName());

        {
            @SuppressWarnings("resource") // Streams.copy closes the input file
            InputStream stream = item.openStream();
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            Streams.copy(stream, baos, true);
        }

        // the second item is over the size max, thus we expect an error
        try {
            // the header is still within size max -> this shall still succeed
            assertTrue(it.hasNext());
        } catch (Exception e) {
            // FileUploadBase.SizeException has protected access:
            if (e.getClass().getSimpleName().equals("SizeException")) {
                fail();
            } else {
                throw e;
            }
        }

        item = it.next();

        try {
            @SuppressWarnings("resource") // Streams.copy closes the input file
            InputStream stream = item.openStream();
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            Streams.copy(stream, baos, true);
            fail();
        } catch (FileUploadIOException e) {
            // expected
        }

    }

}