001/**
002 * Copyright 2015 DuraSpace, Inc.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.fcrepo.client.utils;
017
018import static org.mockito.Matchers.any;
019import static org.mockito.Matchers.eq;
020import static org.mockito.MockitoAnnotations.initMocks;
021import static org.mockito.Mockito.mock;
022import static org.mockito.Mockito.verify;
023import static org.mockito.Mockito.when;
024
025import java.io.ByteArrayInputStream;
026import java.io.IOException;
027import java.io.InputStream;
028import java.util.ArrayList;
029import java.util.HashMap;
030import java.util.List;
031import java.util.Map;
032
033import org.apache.commons.io.IOUtils;
034
035import org.apache.http.Header;
036import org.apache.http.HttpResponse;
037import org.apache.http.StatusLine;
038import org.apache.http.client.HttpClient;
039import org.apache.http.client.methods.HttpGet;
040import org.apache.http.client.methods.HttpHead;
041import org.apache.http.client.methods.HttpPatch;
042import org.apache.http.client.methods.HttpPost;
043import org.apache.http.client.methods.HttpPut;
044import org.apache.http.entity.ByteArrayEntity;
045import org.apache.http.message.BasicHeader;
046
047import org.fcrepo.client.BadRequestException;
048import org.fcrepo.client.FedoraContent;
049import org.fcrepo.client.FedoraException;
050import org.fcrepo.client.FedoraRepository;
051import org.fcrepo.client.ForbiddenException;
052import org.fcrepo.client.NotFoundException;
053import org.fcrepo.client.ReadOnlyException;
054import org.fcrepo.client.impl.FedoraResourceImpl;
055import org.junit.Before;
056import org.junit.Test;
057import org.mockito.Mock;
058
059
060import static org.junit.Assert.assertTrue;
061import static org.junit.Assert.assertEquals;
062
063/**
064 * HttpHelper test
065 * @author escowles
066 * @since 2014-09-04
067 */
068public class HttpHelperTest {
069
070    @Mock
071    private HttpClient mockClient;
072
073    private HttpHelper helper;
074    private HttpHelper readOnlyHelper;
075    private Map<String, List<String>> params;
076
077    private String repoURL = "http://localhost:8080/rest";
078    private String etag = "dummyEtag";
079
080    @Before
081    public void setUp() throws IOException {
082        initMocks(this);
083        helper = new HttpHelper(repoURL, mockClient, false);
084        readOnlyHelper = new HttpHelper(repoURL, mockClient, true);
085
086        final List<String> values = new ArrayList<>();
087        values.add("bar");
088        values.add("baz");
089        params = new HashMap<>();
090        params.put("foo", values);
091    }
092
093    @Test
094    public void testExecuteGet() throws Exception {
095        final HttpGet get = new HttpGet(repoURL);
096        helper.execute(get);
097        verify(mockClient).execute(eq(get));
098    }
099
100    @Test
101    public void testExecutePut() throws Exception {
102        final HttpPut put = new HttpPut(repoURL);
103        helper.execute(put);
104        verify(mockClient).execute(eq(put));
105    }
106
107    @Test
108    public void testExecuteReadOnlyGet() throws Exception {
109        final HttpGet get = new HttpGet(repoURL);
110        readOnlyHelper.execute(get);
111        verify(mockClient).execute(eq(get));
112    }
113
114    @Test (expected = ReadOnlyException.class)
115    public void testExecuteReadOnlyPut() throws Exception {
116        final HttpPut put = new HttpPut(repoURL);
117        readOnlyHelper.execute(put);
118    }
119
120    @Test
121    public void testCreateHeadMethod() {
122        final HttpHead head = helper.createHeadMethod("/foo");
123        assertEquals( repoURL + "/foo", head.getURI().toString() );
124    }
125
126    @Test
127    public void testCreateGetMethod() {
128        final HttpGet get = helper.createGetMethod("/foo", params);
129        assertEquals( repoURL + "/foo?foo=bar&foo=baz", get.getURI().toString() );
130    }
131
132    @Test
133    public void testCreatePatchMethod() throws Exception {
134        final String sparql = "test sparql command";
135        final HttpPatch patch = helper.createPatchMethod("/foo", sparql);
136        assertEquals( repoURL + "/foo", patch.getURI().toString() );
137        assertEquals( "application/sparql-update", patch.getFirstHeader("Content-Type").getValue());
138        assertEquals( sparql, IOUtils.toString(patch.getEntity().getContent()) );
139    }
140
141    @Test (expected = FedoraException.class)
142    public void testCreatePatchMethodEmpty() throws Exception  {
143        helper.createPatchMethod("/foo", "");
144    }
145
146    @Test
147    public void testCreatePostMethod() {
148        final HttpPost post = helper.createPostMethod("/foo", params);
149        assertEquals( repoURL + "/foo?foo=bar&foo=baz", post.getURI().toString() );
150    }
151
152    @Test
153    public void testCreatePutMethod() {
154        final HttpPut put = helper.createPutMethod("/foo", params);
155        assertEquals( repoURL + "/foo?foo=bar&foo=baz", put.getURI().toString() );
156    }
157
158    @Test
159    public void testCreateContentPutMethod() throws Exception {
160        final String dummyContent = "dummy content";
161        final InputStream in = new ByteArrayInputStream( dummyContent.getBytes() );
162        final String mimeType = "text/plain";
163        final String filename = "dummy.txt";
164        final FedoraContent content = new FedoraContent().setContent(in).setContentType(mimeType)
165                .setFilename(filename);
166
167        final HttpPut put = helper.createContentPutMethod("/foo", params, content);
168        assertEquals( repoURL + "/foo?foo=bar&foo=baz", put.getURI().toString() );
169        assertEquals( mimeType, put.getFirstHeader("Content-Type").getValue());
170        assertEquals( dummyContent, IOUtils.toString(put.getEntity().getContent()) );
171        assertEquals( "attachment; filename=\"" + filename + "\"",
172                put.getFirstHeader("Content-Disposition").getValue().toString());
173    }
174
175    @Test
176    public void testCreateTriplesPutMethod() throws Exception {
177        final String dummyContent = "dummy content";
178        final InputStream in = new ByteArrayInputStream( dummyContent.getBytes() );
179        final String mimeType = "text/rdf+n3";
180
181        final HttpPut put = helper.createTriplesPutMethod("/foo", in, mimeType);
182        assertEquals( repoURL + "/foo", put.getURI().toString() );
183        assertEquals( mimeType, put.getFirstHeader("Content-Type").getValue());
184        assertEquals( dummyContent, IOUtils.toString(put.getEntity().getContent()) );
185    }
186
187    @Test (expected = FedoraException.class)
188    public void testCreateTriplesPutMethodWithoutContent() throws Exception {
189        final String mimeType = "text/rdf+n3";
190        helper.createTriplesPutMethod("/foo", null, mimeType);
191    }
192
193    @Test (expected = FedoraException.class)
194    public void testCreateTriplesPutMethodWithoutType() throws Exception {
195        final String dummyContent = "dummy content";
196        final InputStream in = new ByteArrayInputStream( dummyContent.getBytes() );
197        helper.createTriplesPutMethod("/foo", in, "");
198    }
199
200    @Test
201    public void testLoadProperties() throws Exception {
202        final FedoraResourceImpl testResource = testLoadPropertiesWithStatus(200);
203        assertEquals(etag, testResource.getEtagValue() );
204        assertTrue(testResource.getMixins().contains("fedora:resource") );
205    }
206
207    @Test (expected = ForbiddenException.class)
208    public void testLoadPropertiesForbidden() throws Exception {
209        testLoadPropertiesWithStatus(403);
210    }
211
212    @Test (expected = BadRequestException.class)
213    public void testLoadPropertiesBadRequest() throws Exception {
214        testLoadPropertiesWithStatus(400);
215    }
216
217    @Test (expected = NotFoundException.class)
218    public void testLoadPropertiesNotFound() throws Exception {
219        testLoadPropertiesWithStatus(404);
220    }
221
222    private FedoraResourceImpl testLoadPropertiesWithStatus( final int statusCode ) throws Exception {
223        final String triples = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
224            "<rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">" +
225              "<rdf:Description rdf:about=\"http://localhost:8080/rest/foo\">" +
226                "<mixinTypes xmlns=\"http://fedora.info/definitions/v4/repository#\" " +
227                    "rdf:datatype=\"http://www.w3.org/2001/XMLSchema#string\">fedora:resource</mixinTypes>" +
228              "</rdf:Description>" +
229            "</rdf:RDF>";
230        final FedoraRepository mockRepo = mock(FedoraRepository.class);
231        when(mockRepo.getRepositoryUrl()).thenReturn(repoURL);
232        final FedoraResourceImpl origResource = new FedoraResourceImpl(mockRepo, helper, "/foo");
233        final HttpResponse mockResponse = mock(HttpResponse.class);
234        final ByteArrayEntity entity = new ByteArrayEntity(triples.getBytes());
235        entity.setContentType("application/rdf+xml");
236        final Header etagHeader = new BasicHeader("Etag", etag);
237        final Header[] etagHeaders = new Header[]{ etagHeader };
238        final StatusLine mockStatus = mock(StatusLine.class);
239
240        when(mockClient.execute(any(HttpGet.class))).thenReturn(mockResponse);
241        when(mockResponse.getEntity()).thenReturn(entity);
242        when(mockResponse.getHeaders("ETag")).thenReturn(etagHeaders);
243        when(mockResponse.getStatusLine()).thenReturn(mockStatus);
244        when(mockStatus.getStatusCode()).thenReturn(statusCode);
245
246        return helper.loadProperties( origResource );
247    }
248
249}