AbstractSizesTest.java
/*
* 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
*
* https://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 org.apache.commons.fileupload2.core;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import org.apache.commons.io.IOUtils;
import org.junit.jupiter.api.Test;
/**
* Unit test for items with varying sizes.
*
* @param <AFU> The FileUpload type.
* @param <R> The FileUpload request type.
* @param <I> The FileItem type.
* @param <F> The FileItemFactory type.
*/
public abstract class AbstractSizesTest<AFU extends AbstractFileUpload<R, I, F>, R, I extends FileItem<I>, F extends FileItemFactory<I>>
extends AbstractTest<AFU, R, I, F> {
/**
* Checks whether limiting the PartHeaderSizeMax works.
*
* @throws IOException Test failure.
*/
@Test
void testFilePartHeaderSizeMax() throws IOException {
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";
final var upload = newFileUpload();
upload.setMaxPartHeaderSize(200);
final var req = newMockHttpServletRequest(request, null, null);
final var fileItems = upload.parseRequest(req);
assertEquals(1, fileItems.size());
final var item = fileItems.get(0);
assertEquals("This is the content of the file\n", new String(item.get()));
var upload2 = newFileUpload();
upload2.setMaxPartHeaderSize(10);
var req2 = newMockHttpServletRequest(request, null, null);
assertThrows(FileUploadSizeException.class, () -> upload2.parseRequest(req2));
}
/**
* Checks, whether limiting the file size works.
*
* @throws IOException Test failure.
*/
@Test
void testFileSizeLimit() throws IOException {
final var content = "This is the content of the file\n";
final var contentSize = content.getBytes().length;
// @formatter:off
final var request =
"-----1234\r\n" +
"Content-Disposition: form-data; name=\"file\"; filename=\"foo.tab\"\r\n" +
"Content-Type: text/whatever\r\n" +
"\r\n" +
content +
"\r\n" +
"-----1234--\r\n";
// @formatter:on
var upload = newFileUpload();
upload.setMaxFileSize(-1);
var req = newMockHttpServletRequest(request, null, null);
var fileItems = upload.parseRequest(req);
assertEquals(1, fileItems.size());
var item = fileItems.get(0);
assertEquals(content, new String(item.get()));
upload = newFileUpload();
upload.setMaxFileSize(40);
req = newMockHttpServletRequest(request, null, null);
fileItems = upload.parseRequest(req);
assertEquals(1, fileItems.size());
item = fileItems.get(0);
assertEquals(content, new String(item.get()));
upload = newFileUpload();
upload.setMaxFileSize(contentSize);
req = newMockHttpServletRequest(request, null, null);
fileItems = upload.parseRequest(req);
assertEquals(1, fileItems.size());
item = fileItems.get(0);
assertEquals(content, new String(item.get()));
upload = newFileUpload();
upload.setMaxFileSize(contentSize - 1);
req = newMockHttpServletRequest(request, null, null);
try {
upload.parseRequest(req);
fail("Expected exception.");
} catch (final FileUploadByteCountLimitException e) {
assertEquals(contentSize - 1, e.getPermitted());
}
upload = newFileUpload();
upload.setMaxFileSize(30);
req = newMockHttpServletRequest(request, null, null);
try {
upload.parseRequest(req);
fail("Expected exception.");
} catch (final FileUploadByteCountLimitException e) {
assertEquals(30, e.getPermitted());
}
}
/**
* Checks, whether a faked Content-Length header is detected.
*
* @throws IOException Test failure.
*/
@Test
void testFileSizeLimitWithFakedContentLength() throws IOException {
// @formatter:off
final var 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";
// @formatter:on
var upload = newFileUpload();
upload.setMaxFileSize(-1);
var req = newMockHttpServletRequest(request, null, null);
var fileItems = upload.parseRequest(req);
assertEquals(1, fileItems.size());
var item = fileItems.get(0);
assertEquals("This is the content of the file\n", new String(item.get()));
upload = newFileUpload();
upload.setMaxFileSize(40);
req = newMockHttpServletRequest(request, null, null);
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 = newFileUpload();
upload.setMaxFileSize(5);
req = newMockHttpServletRequest(request, null, null);
try {
upload.parseRequest(req);
fail("Expected exception.");
} catch (final FileUploadByteCountLimitException e) {
assertEquals(5, e.getPermitted());
}
// provided Content-Length is wrong, actual content is larger -> handled by LimitedInputStream
upload = newFileUpload();
upload.setMaxFileSize(15);
req = newMockHttpServletRequest(request, null, null);
try {
upload.parseRequest(req);
fail("Expected exception.");
} catch (final FileUploadByteCountLimitException e) {
assertEquals(15, e.getPermitted());
}
}
/**
* Checks whether maxSize works.
*
* @throws IOException Test failure.
*/
@Test
void testMaxSizeLimit() throws IOException {
// @formatter:off
final var 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";
// @formatter:on
final var upload = newFileUpload();
upload.setMaxFileSize(-1);
upload.setMaxSize(200);
final var req = newMockHttpServletRequest(request, null, null);
try {
upload.parseRequest(req);
fail("Expected exception.");
} catch (final FileUploadSizeException e) {
assertEquals(200, e.getPermitted());
}
}
@Test
void testMaxSizeLimitUnknownContentLength() throws IOException {
// @formatter:off
final var 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";
// @formatter:on
final var upload = newFileUpload();
upload.setMaxFileSize(-1);
upload.setMaxSize(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
final var req = newMockHttpServletRequest(request, -1L, 10);
final var it = upload.getItemIterator(req);
assertTrue(it.hasNext());
final var item = it.next();
assertFalse(item.isFormField());
assertEquals("file1", item.getFieldName());
assertEquals("foo1.tab", item.getName());
{
try (final var baos = new ByteArrayOutputStream();
final var stream = item.getInputStream()) {
IOUtils.copy(stream, baos);
}
}
// the second item is over the size max, thus we expect an error
// the header is still within size max -> this shall still succeed
assertTrue(it.hasNext());
assertThrows(FileUploadException.class, () -> {
final var item2 = it.next();
try (final var baos = new ByteArrayOutputStream();
final var stream = item2.getInputStream()) {
IOUtils.copy(stream, baos);
}
});
}
}