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  package org.apache.commons.fileupload2.core;
    18
    19  import static org.junit.jupiter.api.Assertions.assertEquals;
    20  import static org.junit.jupiter.api.Assertions.assertTrue;
    21
    22  import java.io.ByteArrayOutputStream;
    23  import java.io.IOException;
    24  import java.nio.charset.StandardCharsets;
    25
    26  import org.junit.jupiter.api.Test;
    27
    28  /**
    29   * Tests the {@link ProgressListener}.
    30   *
    31   * @param <AFU> The subclass of FileUpload.
    32   * @param <R>   The FileUpload request type.
    33   * @param <I>   The FileItem type.
    34   * @param <F>   The FileItemFactory type.
    35   */
    36  public abstract class AbstractProgressListenerTest<AFU extends AbstractFileUpload<R, I, F>, R, I extends FileItem<I>, F extends FileItemFactory<I>>
    37          extends AbstractTest<AFU, R, I, F> {
    38
    39      protected static class ProgressListenerImpl implements ProgressListener {
    40
    41          private final long expectedContentLength;
    42
    43          private final int expectedItems;
    44
    45          private Long bytesRead;
    46
    47          private Integer items;
    48
    49          ProgressListenerImpl(final long contentLength, final int itemCount) {
    50              expectedContentLength = contentLength;
    51              expectedItems = itemCount;
    52          }
    53
    54          void checkFinished() {
    55              assertEquals(expectedContentLength, bytesRead.longValue());
    56              assertEquals(expectedItems, items.intValue());
    57          }
    58
    59          @Override
    60          public void update(final long actualBytesRead, final long actualContentLength, final int actualItems) {
    61              assertTrue(actualBytesRead >= 0 && actualBytesRead <= expectedContentLength);
    62              assertTrue(actualContentLength == -1 || actualContentLength == expectedContentLength);
    63              assertTrue(actualItems >= 0 && actualItems <= expectedItems);
    64
    65              assertTrue(bytesRead == null || actualBytesRead >= bytesRead.longValue());
    66              bytesRead = Long.valueOf(actualBytesRead);
    67              assertTrue(items == null || actualItems >= items.intValue());
    68              items = Integer.valueOf(actualItems);
    69          }
    70
    71      }
    72
    73      protected void runTest(final int itemCount, final long contentLength, final R request) throws FileUploadException, IOException {
    74          final var upload = newFileUpload();
    75          final var listener = new ProgressListenerImpl(contentLength, itemCount);
    76          upload.setProgressListener(listener);
    77          final var iter = upload.getItemIterator(request);
    78          for (var i = 0; i < itemCount; i++) {
    79              final var idxI = i;
    80              final var fileItemInput = iter.next();
    81              try (final var inputStream = fileItemInput.getInputStream()) {
    82                  for (var j = 0; j < 16_384 + i; j++) {
    83                      final var idxJ = j;
    84                      //
    85                      // 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
    86                      // this:
    87                      //
    88                      final var b1 = (byte) j;
    89                      final var b2 = (byte) inputStream.read();
    90                      assertEquals(b1, b2, () -> String.format("itemCount = %,d, i = %,d, j = %,d", itemCount, idxI, idxJ));
    91                  }
    92                  assertEquals(-1, inputStream.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      * @throws IOException Test failure.
    103      */
    104     @Test
    105     public void testProgressListener() throws IOException {
    106         final var numItems = 512;
    107         final var baos = new ByteArrayOutputStream();
    108         for (var i = 0; i < numItems; i++) {
    109             final var header = "-----1234\r\n" + "Content-Disposition: form-data; name=\"field" + (i + 1) + "\"\r\n" + "\r\n";
    110             baos.write(header.getBytes(StandardCharsets.US_ASCII));
    111             for (var j = 0; j < 16384 + i; j++) {
    112                 baos.write((byte) j);
    113             }
    114             baos.write("\r\n".getBytes(StandardCharsets.US_ASCII));
    115         }
    116         baos.write("-----1234--\r\n".getBytes(StandardCharsets.US_ASCII));
    117         final var requestBytes = baos.toByteArray();
    118
    119         var request = newMockHttpServletRequest(requestBytes, null, Constants.CONTENT_TYPE, null);
    120         runTest(numItems, requestBytes.length, request);
    121         request = newMockHttpServletRequest(requestBytes, -1L, Constants.CONTENT_TYPE, null);
    122         runTest(numItems, requestBytes.length, request);
    123     }
    124
    125 }