    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.File;
    020    import java.io.IOException;
    021    import java.io.OutputStream;
    022    import java.util.Arrays;
    023
    024    import junit.framework.TestCase;
    025    import org.apache.commons.fileupload.DefaultFileItem;
    026    import org.apache.commons.fileupload.DefaultFileItemFactory;
    027
    028
    029    /**
    030     * Unit tests for {@link org.apache.commons.fileupload.DefaultFileItem}.
    031     *
    032     * @author <a href="mailto:martinc@apache.org">Martin Cooper</a>
    033     */
    034    public class DefaultFileItemTest extends TestCase
    035     {
    036
    037        /**
    038         * Content type for regular form items.
    039         */
    040        private static final String textContentType = "text/plain";
    041
    042        /**
    043         * Content type for file uploads.
    044         */
    045        private static final String fileContentType = "application/octet-stream";
    046
    047        /**
    048         * Very low threshold for testing memory versus disk options.
    049         */
    050        private static final int threshold = 16;
    051
    052        /**
    053         * Standard JUnit test case constructor.
    054         *
    055         * @param name The name of the test case.
    056         */
    057        public DefaultFileItemTest(String name)
    058        {
    059            super(name);
    060        }
    061
    062        /**
    063         * Test construction of a regular text field.
    064         */
    065        public void testTextFieldConstruction()
    066        {
    067            FileItemFactory factory = createFactory(null);
    068            String textFieldName = "textField";
    069
    070            FileItem item = factory.createItem(
    071                    textFieldName,
    072                    textContentType,
    073                    true,
    074                    null
    075            );
    076            assertNotNull(item);
    077            assertEquals(item.getFieldName(), textFieldName);
    078            assertEquals(item.getContentType(), textContentType);
    079            assertTrue(item.isFormField());
    080            assertNull(item.getName());
    081        }
    082
    083        /**
    084         * Test construction of a file field.
    085         */
    086        public void testFileFieldConstruction()
    087        {
    088            FileItemFactory factory = createFactory(null);
    089            String fileFieldName = "fileField";
    090            String fileName = "originalFileName";
    091
    092            FileItem item = factory.createItem(
    093                    fileFieldName,
    094                    fileContentType,
    095                    false,
    096                    fileName
    097            );
    098            assertNotNull(item);
    099            assertEquals(item.getFieldName(), fileFieldName);
    100            assertEquals(item.getContentType(), fileContentType);
    101            assertFalse(item.isFormField());
    102            assertEquals(item.getName(), fileName);
    103        }
    104
    105        /**
    106         * Test creation of a field for which the amount of data falls below the
    107         * configured threshold.
    108         */
    109        public void testBelowThreshold()
    110        {
    111            FileItemFactory factory = createFactory(null);
    112            String textFieldName = "textField";
    113            String textFieldValue = "0123456789";
    114            byte[] testFieldValueBytes = textFieldValue.getBytes();
    115
    116            FileItem item = factory.createItem(
    117                    textFieldName,
    118                    textContentType,
    119                    true,
    120                    null
    121            );
    122            assertNotNull(item);
    123
    124            try
    125            {
    126                OutputStream os = item.getOutputStream();
    127                os.write(testFieldValueBytes);
    128                os.close();
    129            }
    130            catch(IOException e)
    131            {
    132                fail("Unexpected IOException");
    133            }
    134            assertTrue(item.isInMemory());
    135            assertEquals(item.getSize(), testFieldValueBytes.length);
    136            assertTrue(Arrays.equals(item.get(), testFieldValueBytes));
    137            assertEquals(item.getString(), textFieldValue);
    138        }
    139
    140        /**
    141         * Test creation of a field for which the amount of data falls above the
    142         * configured threshold, where no specific repository is configured.
    143         */
    144        public void testAboveThresholdDefaultRepository()
    145        {
    146            doTestAboveThreshold(null);
    147        }
    148
    149        /**
    150         * Test creation of a field for which the amount of data falls above the
    151         * configured threshold, where a specific repository is configured.
    152         */
    153        public void testAboveThresholdSpecifiedRepository()
    154        {
    155            String tempPath = System.getProperty("java.io.tmpdir");
    156            String tempDirName = "testAboveThresholdSpecifiedRepository";
    157            File tempDir = new File(tempPath, tempDirName);
    158            tempDir.mkdir();
    159            doTestAboveThreshold(tempDir);
    160            assertTrue(tempDir.delete());
    161        }
    162
    163        /**
    164         * Common code for cases where the amount of data is above the configured
    165         * threshold, but the ultimate destination of the data has not yet been
    166         * determined.
    167         *
    168         * @param repository The directory within which temporary files will be
    169         *                   created.
    170         */
    171        public void doTestAboveThreshold(File repository)
    172        {
    173            FileItemFactory factory = createFactory(repository);
    174            String textFieldName = "textField";
    175            String textFieldValue = "01234567890123456789";
    176            byte[] testFieldValueBytes = textFieldValue.getBytes();
    177
    178            FileItem item = factory.createItem(
    179                    textFieldName,
    180                    textContentType,
    181                    true,
    182                    null
    183            );
    184            assertNotNull(item);
    185
    186            try
    187            {
    188                OutputStream os = item.getOutputStream();
    189                os.write(testFieldValueBytes);
    190                os.close();
    191            }
    192            catch(IOException e)
    193            {
    194                fail("Unexpected IOException");
    195            }
    196            assertFalse(item.isInMemory());
    197            assertEquals(item.getSize(), testFieldValueBytes.length);
    198            assertTrue(Arrays.equals(item.get(), testFieldValueBytes));
    199            assertEquals(item.getString(), textFieldValue);
    200
    201            assertTrue(item instanceof DefaultFileItem);
    202            DefaultFileItem dfi = (DefaultFileItem) item;
    203            File storeLocation = dfi.getStoreLocation();
    204            assertNotNull(storeLocation);
    205            assertTrue(storeLocation.exists());
    206            assertEquals(storeLocation.length(), testFieldValueBytes.length);
    207
    208            if (repository != null)
    209            {
    210                assertEquals(storeLocation.getParentFile(), repository);
    211            }
    212
    213            item.delete();
    214        }
    215
    216
    217        /**
    218         * Creates a new <code>FileItemFactory</code> and returns it, obscuring
    219         * from the caller the underlying implementation of this interface.
    220         *
    221         * @param repository The directory within which temporary files will be
    222         *                   created.
    223         * @return the new <code>FileItemFactory</code> instance.
    224         */
    225        protected FileItemFactory createFactory(File repository)
    226        {
    227            return new DefaultFileItemFactory(threshold, repository);
    228        }
    229
    230
    231        static final String CHARSET_ISO88591 = "ISO-8859-1";
    232        static final String CHARSET_ASCII = "US-ASCII";
    233        static final String CHARSET_UTF8 = "UTF-8";
    234        static final String CHARSET_KOI8_R = "KOI8_R";
    235        static final String CHARSET_WIN1251 = "Cp1251";
    236
    237        static final int SWISS_GERMAN_STUFF_UNICODE [] =
    238        {
    239            0x47, 0x72, 0xFC, 0x65, 0x7A, 0x69, 0x5F, 0x7A, 0xE4, 0x6D, 0xE4
    240        };
    241
    242        static final int SWISS_GERMAN_STUFF_ISO8859_1 [] =
    243        {
    244            0x47, 0x72, 0xFC, 0x65, 0x7A, 0x69, 0x5F, 0x7A, 0xE4, 0x6D, 0xE4
    245        };
    246
    247        static final int SWISS_GERMAN_STUFF_UTF8 [] =
    248        {
    249            0x47, 0x72, 0xC3, 0xBC, 0x65, 0x7A, 0x69, 0x5F, 0x7A, 0xC3, 0xA4,
    250            0x6D, 0xC3, 0xA4
    251        };
    252
    253        static final int RUSSIAN_STUFF_UNICODE [] =
    254        {
    255            0x412, 0x441, 0x435, 0x43C, 0x5F, 0x43F, 0x440, 0x438,
    256            0x432, 0x435, 0x442
    257        };
    258
    259        static final int RUSSIAN_STUFF_UTF8 [] =
    260        {
    261            0xD0, 0x92, 0xD1, 0x81, 0xD0, 0xB5, 0xD0, 0xBC, 0x5F,
    262            0xD0, 0xBF, 0xD1, 0x80, 0xD0, 0xB8, 0xD0, 0xB2, 0xD0,
    263            0xB5, 0xD1, 0x82
    264        };
    265
    266        static final int RUSSIAN_STUFF_KOI8R [] =
    267        {
    268            0xF7, 0xD3, 0xC5, 0xCD, 0x5F, 0xD0, 0xD2, 0xC9, 0xD7,
    269            0xC5, 0xD4
    270        };
    271
    272        static final int RUSSIAN_STUFF_WIN1251 [] =
    273        {
    274            0xC2, 0xF1, 0xE5, 0xEC, 0x5F, 0xEF, 0xF0, 0xE8, 0xE2,
    275            0xE5, 0xF2
    276        };
    277
    278
    279        private static String constructString(int[] unicodeChars)
    280        {
    281            StringBuffer buffer = new StringBuffer();
    282            if (unicodeChars != null)
    283            {
    284                for (int i = 0; i < unicodeChars.length; i++)
    285                {
    286                    buffer.append((char) unicodeChars[i]);
    287                }
    288            }
    289            return buffer.toString();
    290        }
    291
    292        /**
    293         * Test construction of content charset.
    294         */
    295        public void testContentCharSet() throws Exception
    296        {
    297            FileItemFactory factory = createFactory(null);
    298
    299            String teststr = constructString(SWISS_GERMAN_STUFF_UNICODE);
    300
    301            FileItem item =
    302                factory.createItem(
    303                    "doesnotmatter",
    304                    "text/plain; charset=" + CHARSET_ISO88591,
    305                    true,
    306                    null);
    307            OutputStream outstream = item.getOutputStream();
    308            for (int i = 0; i < SWISS_GERMAN_STUFF_ISO8859_1.length; i++)
    309            {
    310                outstream.write(SWISS_GERMAN_STUFF_ISO8859_1[i]);
    311            }
    312            outstream.close();
    313            assertEquals(teststr, teststr, item.getString());
    314
    315            item =
    316                factory.createItem(
    317                    "doesnotmatter",
    318                    "text/plain; charset=" + CHARSET_UTF8,
    319                    true,
    320                    null);
    321            outstream = item.getOutputStream();
    322            for (int i = 0; i < SWISS_GERMAN_STUFF_UTF8.length; i++)
    323            {
    324                outstream.write(SWISS_GERMAN_STUFF_UTF8[i]);
    325            }
    326            outstream.close();
    327            assertEquals(teststr, teststr, item.getString());
    328
    329            teststr = constructString(RUSSIAN_STUFF_UNICODE);
    330
    331            item =
    332                factory.createItem(
    333                    "doesnotmatter",
    334                    "text/plain; charset=" + CHARSET_KOI8_R,
    335                    true,
    336                    null);
    337            outstream = item.getOutputStream();
    338            for (int i = 0; i < RUSSIAN_STUFF_KOI8R.length; i++)
    339            {
    340                outstream.write(RUSSIAN_STUFF_KOI8R[i]);
    341            }
    342            outstream.close();
    343            assertEquals(teststr, teststr, item.getString());
    344
    345            item =
    346                factory.createItem(
    347                    "doesnotmatter",
    348                    "text/plain; charset=" + CHARSET_WIN1251,
    349                    true,
    350                    null);
    351            outstream = item.getOutputStream();
    352            for (int i = 0; i < RUSSIAN_STUFF_WIN1251.length; i++)
    353            {
    354                outstream.write(RUSSIAN_STUFF_WIN1251[i]);
    355            }
    356            outstream.close();
    357            assertEquals(teststr, teststr, item.getString());
    358
    359            item =
    360                factory.createItem(
    361                    "doesnotmatter",
    362                    "text/plain; charset=" + CHARSET_UTF8,
    363                    true,
    364                    null);
    365            outstream = item.getOutputStream();
    366            for (int i = 0; i < RUSSIAN_STUFF_UTF8.length; i++)
    367            {
    368                outstream.write(RUSSIAN_STUFF_UTF8[i]);
    369            }
    370            outstream.close();
    371            assertEquals(teststr, teststr, item.getString());
    372        }
    373    }