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 }