001package org.apache.fulcrum.upload;
002
003import static org.junit.jupiter.api.Assertions.assertEquals;
004import static org.junit.jupiter.api.Assertions.assertNotNull;
005import static org.junit.jupiter.api.Assertions.assertTrue;
006import static org.junit.jupiter.api.Assertions.fail;
007import static org.mockito.ArgumentMatchers.any;
008import static org.mockito.ArgumentMatchers.anyInt;
009import static org.mockito.ArgumentMatchers.anyString;
010import static org.mockito.Mockito.doAnswer;
011import static org.mockito.Mockito.mock;
012import static org.mockito.Mockito.when;
013
014import java.io.ByteArrayInputStream;
015
016/*
017 * Licensed to the Apache Software Foundation (ASF) under one
018 * or more contributor license agreements.  See the NOTICE file
019 * distributed with this work for additional information
020 * regarding copyright ownership.  The ASF licenses this file
021 * to you under the Apache License, Version 2.0 (the
022 * "License"); you may not use this file except in compliance
023 * with the License.  You may obtain a copy of the License at
024 *
025 *   http://www.apache.org/licenses/LICENSE-2.0
026 *
027 * Unless required by applicable law or agreed to in writing,
028 * software distributed under the License is distributed on an
029 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
030 * KIND, either express or implied.  See the License for the
031 * specific language governing permissions and limitations
032 * under the License.
033 */
034
035
036import java.io.File;
037import java.io.IOException;
038import java.util.HashMap;
039import java.util.List;
040import java.util.Locale;
041import java.util.Map;
042import java.util.Vector;
043
044import javax.servlet.ReadListener;
045import javax.servlet.ServletInputStream;
046import javax.servlet.http.HttpServletRequest;
047import javax.servlet.http.HttpSession;
048
049import org.apache.avalon.framework.component.ComponentException;
050import org.apache.commons.fileupload.FileItem;
051import org.apache.commons.fileupload.FileItemIterator;
052import org.apache.fulcrum.testcontainer.BaseUnit5Test;
053import org.junit.jupiter.api.BeforeEach;
054import org.junit.jupiter.api.Test;
055import org.mockito.invocation.InvocationOnMock;
056import org.mockito.stubbing.Answer;
057/**
058 * UploadServiceTest
059 *
060 * @author <a href="epugh@upstate.com">Eric Pugh</a>
061 * @version $Id$
062 */
063public class UploadServiceTest extends BaseUnit5Test
064{
065    private UploadService uploadService = null;
066
067
068    @BeforeEach
069    public void setUp() throws Exception
070    {
071        try
072        {
073            uploadService = (UploadService) this.lookup(UploadService.ROLE);
074        }
075        catch (ComponentException e)
076        {
077            e.printStackTrace();
078            fail(e.getMessage());
079        }
080    }
081    /**
082     * Simple test that verify an object can be created and deleted.
083     * @throws Exception
084     */
085    @Test
086    public void testRepositoryExists() throws Exception
087    {
088        File f = new File(uploadService.getRepository());
089        assertTrue(f.exists());
090    }
091    
092    // This is Apache Commons, but we want to make be really sure it runs clean in Fulcrum
093    @Test
094    public void testUploadEncoding() throws Exception {
095        HttpServletRequest request = getMockRequest();
096        when(request.getContentType()).thenReturn("multipart/form-data; boundary=boundary");
097        when(request.getContentLength()).thenReturn(-1);// -1
098        when(request.getMethod()).thenReturn("post");
099        String testData= "Überfülle=\r\nf";
100        //override default settings
101        requestFormData( request, testData );
102        assertTrue(uploadService.isMultipart( request ));
103        List<FileItem> fil = uploadService.parseRequest( request );
104        assertNotNull(fil);
105        assertTrue( fil.size() >0);
106        FileItem fi = fil.get( 0 );
107        System.out.println( fi.getString() );
108        assertEquals(15,fi.getSize());
109        // default is ISO-8859-1
110        assertTrue( fi.getString("UTF-8").startsWith( "Überfülle" ), "data string:'" +fi.getString("UTF-8") +"' not as expected");
111        
112        //reset inputstream
113        requestFormData( request, testData);
114        FileItemIterator fii = uploadService.getItemIterator( request );
115        assertNotNull(fii);
116        assertTrue( fii.hasNext());
117        assertNotNull(fii.next());
118    }
119
120    private void requestFormData( HttpServletRequest request, String data)
121        throws IOException
122    {
123        String example ="--boundary\r\n"
124            + "Content-Disposition: form-data; name=\"uploadedfile\"; filename=\"12345678.txt\"\r\n"
125            + "Content-Type: text/plain\r\n"
126//            + "Content-Transfer-Encoding: UTF-8\r\n"
127            + "\r\n"
128            + data 
129            + "\r\n--boundary--\r\n";
130        final ByteArrayInputStream is = new ByteArrayInputStream (example.getBytes());// "UTF-8"
131        when(request.getInputStream()).thenReturn(new ServletInputStream() {
132                @Override
133                public int read() throws IOException {
134                    return is.read();
135                }
136
137                                @Override
138                                public boolean isFinished() {
139                                        // TODO Auto-generated method stub
140                                        return false;
141                                }
142
143                                @Override
144                                public boolean isReady() {
145                                        // TODO Auto-generated method stub
146                                        return false;
147                                }
148
149                                @Override
150                                public void setReadListener(ReadListener readListener) {
151                                        // TODO Auto-generated method stub
152                                        
153                                }
154            });
155    }
156    
157    protected Map<String,Object> attributes = new HashMap<String,Object>();
158    protected int maxInactiveInterval = 0;
159    // from Turbine org.apache.turbine.test.BaseTestCase, should be later in Fulcrum Testcontainer BaseUnit4Test
160    protected HttpServletRequest getMockRequest()
161    {
162        HttpServletRequest request = mock(HttpServletRequest.class);
163        HttpSession session = mock(HttpSession.class);
164
165        doAnswer(new Answer<Object>()
166        {
167            @Override
168            public Object answer(InvocationOnMock invocation) throws Throwable
169            {
170                String key = (String) invocation.getArguments()[0];
171                return attributes.get(key);
172            }
173        }).when(session).getAttribute(anyString());
174
175        doAnswer(new Answer<Object>()
176        {
177            @Override
178            public Object answer(InvocationOnMock invocation) throws Throwable
179            {
180                String key = (String) invocation.getArguments()[0];
181                Object value = invocation.getArguments()[1];
182                attributes.put(key, value);
183                return null;
184            }
185        }).when(session).setAttribute(anyString(), any());
186
187        when(session.getMaxInactiveInterval()).thenReturn(maxInactiveInterval);
188
189        doAnswer(new Answer<Integer>()
190        {
191            @Override
192            public Integer answer(InvocationOnMock invocation) throws Throwable
193            {
194                return Integer.valueOf(maxInactiveInterval);
195            }
196        }).when(session).getMaxInactiveInterval();
197
198        doAnswer(new Answer<Object>()
199        {
200            @Override
201            public Object answer(InvocationOnMock invocation) throws Throwable
202            {
203                Integer value = (Integer) invocation.getArguments()[0];
204                maxInactiveInterval = value.intValue();
205                return null;
206            }
207        }).when(session).setMaxInactiveInterval(anyInt());
208
209        when(session.isNew()).thenReturn(true);
210        when(request.getSession()).thenReturn(session);
211
212        when(request.getServerName()).thenReturn("bob");
213        when(request.getProtocol()).thenReturn("http");
214        when(request.getScheme()).thenReturn("scheme");
215        when(request.getPathInfo()).thenReturn("damn");
216        when(request.getServletPath()).thenReturn("damn2");
217        when(request.getContextPath()).thenReturn("wow");
218        when(request.getContentType()).thenReturn("html/text");
219
220        when(request.getCharacterEncoding()).thenReturn("UTF-8");
221        when(request.getServerPort()).thenReturn(8080);
222        when(request.getLocale()).thenReturn(Locale.US);
223
224        when(request.getHeader("Content-type")).thenReturn("html/text");
225        when(request.getHeader("Accept-Language")).thenReturn("en-US");
226
227        Vector<String> v = new Vector<String>();
228        when(request.getParameterNames()).thenReturn(v.elements());
229        return request;
230    }
231}