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.fileupload;
    18
    19  import static org.junit.Assert.assertEquals;
    20  import static org.junit.Assert.assertFalse;
    21  import static org.junit.Assert.assertNotNull;
    22  import static org.junit.Assert.assertTrue;
    23  import static org.junit.Assert.fail;
    24
    25  import java.io.ByteArrayInputStream;
    26  import java.io.ByteArrayOutputStream;
    27  import java.io.File;
    28  import java.io.IOException;
    29  import java.io.ObjectInputStream;
    30  import java.io.ObjectOutputStream;
    31  import java.io.OutputStream;
    32
    33  import org.apache.commons.fileupload.disk.DiskFileItemFactory;
    34  import org.apache.commons.io.FileUtils;
    35  import org.junit.After;
    36  import org.junit.Before;
    37  import org.junit.Test;
    38
    39  /**
    40   * Serialization Unit tests for
    41   *  {@link org.apache.commons.fileupload.disk.DiskFileItem}.
    42   */
    43  public class DiskFileItemSerializeTest {
    44
    45      // Use a private repo to catch any files left over by tests
    46      private static final File REPO = new File(System.getProperty("java.io.tmpdir"), "diskfileitemrepo");
    47
    48      @Before
    49      public void setUp() throws Exception {
    50          if (REPO.exists()) {
    51              FileUtils.deleteDirectory(REPO);
    52          }
    53          assertFalse("Must not exist", REPO.exists());
    54          REPO.mkdir();
    55      }
    56
    57      @After
    58      public void tearDown() {
    59          for(File file : FileUtils.listFiles(REPO, null, true)) {
    60              System.out.println("Found leftover file " + file);
    61          }
    62          REPO.delete();
    63          assertFalse(REPO + " is not empty", REPO.exists());
    64      }
    65
    66      /**
    67       * Content type for regular form items.
    68       */
    69      private static final String textContentType = "text/plain";
    70
    71      /**
    72       * Very low threshold for testing memory versus disk options.
    73       */
    74      private static final int threshold = 16;
    75
    76      /**
    77       * Helper method to test creation of a field when a repository is used.
    78       */
    79      public void testInMemoryObject(byte[] testFieldValueBytes, File repository) {
    80          FileItem item = createFileItem(testFieldValueBytes, repository);
    81
    82          // Check state is as expected
    83          assertTrue("Initial: in memory", item.isInMemory());
    84          assertEquals("Initial: size", item.getSize(), testFieldValueBytes.length);
    85          compareBytes("Initial", item.get(), testFieldValueBytes);
    86          item.delete();
    87      }
    88
    89      /**
    90       * Helper method to test creation of a field.
    91       */
    92      private void testInMemoryObject(byte[] testFieldValueBytes) {
    93          testInMemoryObject(testFieldValueBytes, REPO);
    94      }
    95
    96      /**
    97       * Test creation of a field for which the amount of data falls below the
    98       * configured threshold.
    99       */
    100     @Test
    101     public void testBelowThreshold() throws Exception {
    102         // Create the FileItem
    103         byte[] testFieldValueBytes = createContentBytes(threshold - 1);
    104         testInMemoryObject(testFieldValueBytes);
    105     }
    106
    107     /**
    108      * Test creation of a field for which the amount of data equals the
    109      * configured threshold.
    110      */
    111     @Test
    112     public void testThreshold() throws Exception {
    113         // Create the FileItem
    114         byte[] testFieldValueBytes = createContentBytes(threshold);
    115         testInMemoryObject(testFieldValueBytes);
    116     }
    117
    118     /**
    119      * Test creation of a field for which the amount of data falls above the
    120      * configured threshold.
    121      */
    122     @Test
    123     public void testAboveThreshold() throws Exception {
    124         // Create the FileItem
    125         byte[] testFieldValueBytes = createContentBytes(threshold + 1);
    126         FileItem item = createFileItem(testFieldValueBytes);
    127
    128         // Check state is as expected
    129         assertFalse("Initial: in memory", item.isInMemory());
    130         assertEquals("Initial: size", item.getSize(), testFieldValueBytes.length);
    131         compareBytes("Initial", item.get(), testFieldValueBytes);
    132
    133         item.delete();
    134     }
    135
    136     /**
    137      * Test serialization and deserialization when repository is not null.
    138      */
    139     @Test
    140     public void testValidRepository() throws Exception {
    141         // Create the FileItem
    142         byte[] testFieldValueBytes = createContentBytes(threshold);
    143         testInMemoryObject(testFieldValueBytes, REPO);
    144     }
    145
    146     /**
    147      * Test deserialization fails when repository is not valid.
    148      */
    149     @Test(expected=IOException.class)
    150     public void testInvalidRepository() throws Exception {
    151         // Create the FileItem
    152         byte[] testFieldValueBytes = createContentBytes(threshold);
    153         File repository = new File(System.getProperty("java.io.tmpdir"), "file");
    154         FileItem item = createFileItem(testFieldValueBytes, repository);
    155         deserialize(serialize(item));
    156     }
    157
    158     /**
    159      * Test deserialization fails when repository contains a null character.
    160      */
    161     @Test(expected=IOException.class)
    162     public void testInvalidRepositoryWithNullChar() throws Exception {
    163         // Create the FileItem
    164         byte[] testFieldValueBytes = createContentBytes(threshold);
    165         File repository = new File(System.getProperty("java.io.tmpdir"), "\0");
    166         FileItem item = createFileItem(testFieldValueBytes, repository);
    167         deserialize(serialize(item));
    168     }
    169
    170     /**
    171      * Compare content bytes.
    172      */
    173     private void compareBytes(String text, byte[] origBytes, byte[] newBytes) {
    174         assertNotNull("origBytes must not be null", origBytes);
    175         assertNotNull("newBytes must not be null", newBytes);
    176         assertEquals(text + " byte[] length", origBytes.length, newBytes.length);
    177         for (int i = 0; i < origBytes.length; i++) {
    178             assertEquals(text + " byte[" + i + "]", origBytes[i], newBytes[i]);
    179         }
    180     }
    181
    182     /**
    183      * Create content bytes of a specified size.
    184      */
    185     private byte[] createContentBytes(int size) {
    186         StringBuilder buffer = new StringBuilder(size);
    187         byte count = 0;
    188         for (int i = 0; i < size; i++) {
    189             buffer.append(count+"");
    190             count++;
    191             if (count > 9) {
    192                 count = 0;
    193             }
    194         }
    195         return buffer.toString().getBytes();
    196     }
    197
    198     /**
    199      * Create a FileItem with the specfied content bytes and repository.
    200      */
    201     private FileItem createFileItem(byte[] contentBytes, File repository) {
    202         FileItemFactory factory = new DiskFileItemFactory(threshold, repository);
    203         String textFieldName = "textField";
    204
    205         FileItem item = factory.createItem(
    206                 textFieldName,
    207                 textContentType,
    208                 true,
    209                 "My File Name"
    210         );
    211         try {
    212             OutputStream os = item.getOutputStream();
    213             os.write(contentBytes);
    214             os.close();
    215         } catch(IOException e) {
    216             fail("Unexpected IOException" + e);
    217         }
    218
    219         return item;
    220
    221     }
    222
    223     /**
    224      * Create a FileItem with the specfied content bytes.
    225      */
    226     private FileItem createFileItem(byte[] contentBytes) {
    227         return createFileItem(contentBytes, REPO);
    228     }
    229
    230     /**
    231      * Do serialization
    232      */
    233     private ByteArrayOutputStream serialize(Object target) throws Exception {
    234         ByteArrayOutputStream baos = new ByteArrayOutputStream();
    235         ObjectOutputStream oos = new ObjectOutputStream(baos);
    236         oos.writeObject(target);
    237         oos.flush();
    238         oos.close();
    239         return baos;
    240     }
    241
    242     /**
    243      * Do deserialization
    244      */
    245     private Object deserialize(ByteArrayOutputStream baos) throws Exception {
    246         Object result = null;
    247         ByteArrayInputStream bais =
    248                 new ByteArrayInputStream(baos.toByteArray());
    249         ObjectInputStream ois = new ObjectInputStream(bais);
    250         result = ois.readObject();
    251         bais.close();
    252
    253         return result;
    254     }
    255 }