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; 017 018import static java.net.URI.create; 019import static org.fcrepo.client.TestUtils.baseUrl; 020import static org.fcrepo.client.TestUtils.rdfXml; 021import static org.fcrepo.client.TestUtils.setField; 022import static org.fcrepo.client.TestUtils.sparqlUpdate; 023import static org.fcrepo.client.TestUtils.RDF_XML; 024import static org.fcrepo.client.TestUtils.SPARQL_UPDATE; 025import static org.fcrepo.client.TestUtils.TEXT_TURTLE; 026import static org.junit.Assert.assertEquals; 027import static org.mockito.Matchers.any; 028import static org.mockito.Mockito.when; 029 030import java.io.ByteArrayInputStream; 031import java.io.InputStream; 032import java.io.IOException; 033import java.net.URI; 034 035import org.apache.commons.io.IOUtils; 036import org.apache.http.Header; 037import org.apache.http.HttpEntity; 038import org.apache.http.StatusLine; 039import org.apache.http.client.methods.CloseableHttpResponse; 040import org.apache.http.client.methods.HttpUriRequest; 041import org.apache.http.entity.ByteArrayEntity; 042import org.apache.http.impl.client.CloseableHttpClient; 043import org.apache.http.message.BasicHeader; 044import org.junit.Before; 045import org.junit.Test; 046import org.junit.runner.RunWith; 047import org.mockito.Mock; 048import org.mockito.runners.MockitoJUnitRunner; 049 050/** 051 * @author acoburn 052 */ 053@RunWith(MockitoJUnitRunner.class) 054public class FcrepoClientTest { 055 056 private FcrepoClient testClient; 057 058 @Mock 059 private CloseableHttpClient mockHttpclient; 060 061 @Mock 062 private CloseableHttpResponse mockResponse; 063 064 @Mock 065 private StatusLine mockStatus; 066 067 @Mock 068 private HttpEntity mockEntity; 069 070 @Before 071 public void setUp() throws IOException { 072 testClient = new FcrepoClient(null, null, null, true); 073 setField(testClient, "httpclient", mockHttpclient); 074 } 075 076 @Test 077 public void testGet() throws IOException, FcrepoOperationFailedException { 078 final int status = 200; 079 final URI uri = create(baseUrl); 080 final ByteArrayEntity entity = new ByteArrayEntity(rdfXml.getBytes()); 081 entity.setContentType(RDF_XML); 082 083 doSetupMockRequest(RDF_XML, entity, status); 084 085 final FcrepoResponse response = testClient.get(uri, RDF_XML, "return=minimal"); 086 087 assertEquals(response.getUrl(), uri); 088 assertEquals(response.getStatusCode(), status); 089 assertEquals(response.getContentType(), RDF_XML); 090 assertEquals(response.getLocation(), null); 091 assertEquals(IOUtils.toString(response.getBody()), rdfXml); 092 } 093 094 @Test (expected = FcrepoOperationFailedException.class) 095 public void testGetError() throws Exception { 096 final int status = 400; 097 final URI uri = create(baseUrl); 098 final ByteArrayEntity entity = new ByteArrayEntity(rdfXml.getBytes()); 099 entity.setContentType(RDF_XML); 100 101 doSetupMockRequest(RDF_XML, entity, status); 102 testClient.get(uri, RDF_XML, "return=representation"); 103 } 104 105 @Test (expected = FcrepoOperationFailedException.class) 106 public void testGet100() throws Exception { 107 final int status = 100; 108 final URI uri = create(baseUrl); 109 final ByteArrayEntity entity = new ByteArrayEntity(rdfXml.getBytes()); 110 entity.setContentType(RDF_XML); 111 112 doSetupMockRequest(RDF_XML, entity, status); 113 testClient.get(uri, RDF_XML, null); 114 } 115 116 @Test 117 public void testGet300() throws Exception { 118 final int status = 300; 119 final URI uri = create(baseUrl); 120 final String redirect = baseUrl + "/bar"; 121 final Header linkHeader = new BasicHeader("Link", "<" + redirect + ">; rel=\"describedby\""); 122 final Header[] headers = new Header[] { linkHeader }; 123 final CloseableHttpResponse mockResponse = doSetupMockRequest(RDF_XML, null, status); 124 125 when(mockResponse.getHeaders("Link")).thenReturn(headers); 126 127 final FcrepoResponse response = testClient.get(uri, RDF_XML, null); 128 129 assertEquals(response.getUrl(), uri); 130 assertEquals(response.getStatusCode(), status); 131 assertEquals(response.getContentType(), RDF_XML); 132 assertEquals(response.getLocation(), create(redirect)); 133 assertEquals(response.getBody(), null); 134 } 135 136 @Test 137 public void testGetNoAccept() throws Exception { 138 final int status = 200; 139 final URI uri = create(baseUrl); 140 141 doSetupMockRequest(RDF_XML, null, status); 142 143 final FcrepoResponse response = testClient.get(uri, null, null); 144 145 assertEquals(response.getUrl(), uri); 146 assertEquals(response.getStatusCode(), status); 147 assertEquals(response.getContentType(), RDF_XML); 148 assertEquals(response.getLocation(), null); 149 assertEquals(response.getBody(), null); 150 } 151 152 @Test 153 public void testHead() throws IOException, FcrepoOperationFailedException { 154 final int status = 200; 155 final URI uri = create(baseUrl); 156 157 doSetupMockRequest(TEXT_TURTLE, null, status); 158 159 final FcrepoResponse response = testClient.head(uri); 160 161 assertEquals(response.getUrl(), uri); 162 assertEquals(response.getStatusCode(), status); 163 assertEquals(response.getContentType(), TEXT_TURTLE); 164 assertEquals(response.getLocation(), null); 165 assertEquals(response.getBody(), null); 166 } 167 168 @Test (expected = FcrepoOperationFailedException.class) 169 public void testHeadError() throws IOException, FcrepoOperationFailedException { 170 doSetupMockRequest(TEXT_TURTLE, null, 404); 171 testClient.head(create(baseUrl)); 172 } 173 174 @Test 175 public void testPut() throws IOException, FcrepoOperationFailedException { 176 final int status = 204; 177 final URI uri = create(baseUrl); 178 final InputStream body = new ByteArrayInputStream(rdfXml.getBytes()); 179 180 doSetupMockRequest(RDF_XML, null, status); 181 182 final FcrepoResponse response = testClient.put(uri, body, RDF_XML); 183 184 assertEquals(response.getUrl(), uri); 185 assertEquals(response.getStatusCode(), status); 186 assertEquals(response.getContentType(), RDF_XML); 187 assertEquals(response.getLocation(), null); 188 assertEquals(response.getBody(), null); 189 } 190 191 @Test 192 public void testPutNoBody() throws IOException, FcrepoOperationFailedException { 193 final int status = 204; 194 final URI uri = create(baseUrl); 195 196 doSetupMockRequest(null, null, status); 197 198 final FcrepoResponse response = testClient.put(uri, null, null); 199 200 assertEquals(response.getUrl(), uri); 201 assertEquals(response.getStatusCode(), status); 202 assertEquals(response.getContentType(), null); 203 assertEquals(response.getLocation(), null); 204 assertEquals(response.getBody(), null); 205 } 206 207 @Test 208 public void testPutWithResponseBody() throws IOException, FcrepoOperationFailedException { 209 final int status = 201; 210 final URI uri = create(baseUrl); 211 212 doSetupMockRequest(null, new ByteArrayEntity(uri.toString().getBytes()), status); 213 214 final FcrepoResponse response = testClient.put(uri, null, null); 215 216 assertEquals(response.getUrl(), uri); 217 assertEquals(response.getStatusCode(), status); 218 assertEquals(response.getContentType(), null); 219 assertEquals(response.getLocation(), null); 220 assertEquals(IOUtils.toString(response.getBody()), uri.toString()); 221 } 222 223 @Test (expected = FcrepoOperationFailedException.class) 224 public void testPutError() throws IOException, FcrepoOperationFailedException { 225 final int status = 500; 226 final URI uri = create(baseUrl); 227 final InputStream body = new ByteArrayInputStream(rdfXml.getBytes()); 228 229 doSetupMockRequest(RDF_XML, null, status); 230 testClient.put(uri, body, RDF_XML); 231 } 232 233 @Test 234 public void testDelete() throws IOException, FcrepoOperationFailedException { 235 final int status = 204; 236 final URI uri = create(baseUrl); 237 238 doSetupMockRequest(SPARQL_UPDATE, null, status); 239 240 final FcrepoResponse response = testClient.delete(uri); 241 242 assertEquals(response.getUrl(), uri); 243 assertEquals(response.getStatusCode(), status); 244 assertEquals(response.getContentType(), SPARQL_UPDATE); 245 assertEquals(response.getLocation(), null); 246 assertEquals(response.getBody(), null); 247 } 248 249 @Test 250 public void testDeleteWithResponseBody() throws IOException, FcrepoOperationFailedException { 251 final int status = 204; 252 final URI uri = create(baseUrl); 253 final String responseText = "tombstone found"; 254 255 doSetupMockRequest(null, new ByteArrayEntity(responseText.getBytes()), status); 256 257 final FcrepoResponse response = testClient.delete(uri); 258 259 assertEquals(response.getUrl(), uri); 260 assertEquals(response.getStatusCode(), status); 261 assertEquals(response.getContentType(), null); 262 assertEquals(response.getLocation(), null); 263 assertEquals(IOUtils.toString(response.getBody()), responseText); 264 } 265 266 @Test (expected = FcrepoOperationFailedException.class) 267 public void testDeleteError() throws IOException, FcrepoOperationFailedException { 268 final int status = 401; 269 final URI uri = create(baseUrl); 270 271 doSetupMockRequest(SPARQL_UPDATE, null, status); 272 testClient.delete(uri); 273 } 274 275 @Test 276 public void testPatch() throws IOException, FcrepoOperationFailedException { 277 final int status = 204; 278 final URI uri = create(baseUrl); 279 final InputStream body = new ByteArrayInputStream(sparqlUpdate.getBytes()); 280 281 doSetupMockRequest(SPARQL_UPDATE, null, status); 282 283 final FcrepoResponse response = testClient.patch(uri, body); 284 285 assertEquals(response.getUrl(), uri); 286 assertEquals(response.getStatusCode(), status); 287 assertEquals(response.getContentType(), SPARQL_UPDATE); 288 assertEquals(response.getLocation(), null); 289 assertEquals(response.getBody(), null); 290 } 291 292 @Test (expected = IllegalArgumentException.class) 293 public void testPatchNoContent() throws IOException, FcrepoOperationFailedException { 294 final int status = 204; 295 final URI uri = create(baseUrl); 296 297 doSetupMockRequest(SPARQL_UPDATE, null, status); 298 testClient.patch(uri, null); 299 } 300 301 @Test 302 public void testPatchResponseBody() throws IOException, FcrepoOperationFailedException { 303 final int status = 204; 304 final URI uri = create(baseUrl); 305 final String responseText = "Sparql-update response"; 306 final InputStream body = new ByteArrayInputStream(sparqlUpdate.getBytes()); 307 308 doSetupMockRequest(SPARQL_UPDATE, new ByteArrayEntity(responseText.getBytes()), status); 309 310 final FcrepoResponse response = testClient.patch(uri, body); 311 312 assertEquals(response.getUrl(), uri); 313 assertEquals(response.getStatusCode(), status); 314 assertEquals(response.getContentType(), SPARQL_UPDATE); 315 assertEquals(IOUtils.toString(response.getBody()), responseText); 316 } 317 318 @Test (expected = FcrepoOperationFailedException.class) 319 public void testPatchError() throws IOException, FcrepoOperationFailedException { 320 final int status = 415; 321 final URI uri = create(baseUrl); 322 final InputStream body = new ByteArrayInputStream(sparqlUpdate.getBytes()); 323 324 doSetupMockRequest(SPARQL_UPDATE, null, status); 325 testClient.patch(uri, body); 326 } 327 328 @Test 329 public void testPost() throws IOException, FcrepoOperationFailedException { 330 final int status = 204; 331 final URI uri = create(baseUrl); 332 final InputStream body = new ByteArrayInputStream(sparqlUpdate.getBytes()); 333 334 doSetupMockRequest(SPARQL_UPDATE, null, status); 335 336 final FcrepoResponse response = testClient.post(uri, body, SPARQL_UPDATE); 337 338 assertEquals(response.getUrl(), uri); 339 assertEquals(response.getStatusCode(), status); 340 assertEquals(response.getContentType(), SPARQL_UPDATE); 341 assertEquals(response.getLocation(), null); 342 assertEquals(response.getBody(), null); 343 } 344 345 @Test 346 public void testPostResponseBody() throws IOException, FcrepoOperationFailedException { 347 final int status = 204; 348 final URI uri = create(baseUrl); 349 final String responseText = baseUrl + "/bar"; 350 final InputStream body = new ByteArrayInputStream(sparqlUpdate.getBytes()); 351 352 doSetupMockRequest(SPARQL_UPDATE, new ByteArrayEntity(responseText.getBytes()), status); 353 354 final FcrepoResponse response = testClient.post(uri, body, SPARQL_UPDATE); 355 356 assertEquals(response.getUrl(), uri); 357 assertEquals(response.getStatusCode(), status); 358 assertEquals(response.getContentType(), SPARQL_UPDATE); 359 assertEquals(response.getLocation(), null); 360 assertEquals(IOUtils.toString(response.getBody()), responseText); 361 } 362 363 @Test 364 public void testPostNoBody() throws IOException, FcrepoOperationFailedException { 365 final int status = 204; 366 final URI uri = create(baseUrl); 367 final String responseText = baseUrl + "/bar"; 368 369 doSetupMockRequest(null, new ByteArrayEntity(responseText.getBytes()), status); 370 371 final FcrepoResponse response = testClient.post(uri, null, null); 372 373 assertEquals(response.getUrl(), uri); 374 assertEquals(response.getStatusCode(), status); 375 assertEquals(response.getContentType(), null); 376 assertEquals(response.getLocation(), null); 377 assertEquals(IOUtils.toString(response.getBody()), responseText); 378 } 379 380 @Test (expected = FcrepoOperationFailedException.class) 381 public void testPostError() throws IOException, FcrepoOperationFailedException { 382 final int status = 415; 383 final URI uri = create(baseUrl); 384 final InputStream body = new ByteArrayInputStream(sparqlUpdate.getBytes()); 385 386 doSetupMockRequest(SPARQL_UPDATE, null, status); 387 testClient.post(uri, body, SPARQL_UPDATE); 388 } 389 390 @Test 391 public void testPostErrorNullUrl() throws IOException, FcrepoOperationFailedException { 392 final int status = 401; 393 final String statusPhrase = "Unauthorized"; 394 final String response = "Response error"; 395 final InputStream body = new ByteArrayInputStream(sparqlUpdate.getBytes()); 396 final ByteArrayEntity responseBody = new ByteArrayEntity(response.getBytes()); 397 final Header contentTypeHeader = new BasicHeader("Content-Type", SPARQL_UPDATE); 398 final Header[] responseHeaders = new Header[]{ contentTypeHeader }; 399 400 doSetupMockRequest(SPARQL_UPDATE, responseBody, status, statusPhrase); 401 402 when(mockResponse.getAllHeaders()).thenReturn(null); 403 404 try { 405 testClient.post(null, body, SPARQL_UPDATE); 406 } catch (FcrepoOperationFailedException ex) { 407 assertEquals(ex.getUrl(), null); 408 assertEquals(ex.getStatusText(), statusPhrase); 409 assertEquals(ex.getStatusCode(), status); 410 } 411 } 412 413 @Test 414 public void testBadRequest() throws IOException, FcrepoOperationFailedException { 415 final URI uri = create(baseUrl); 416 final InputStream body = new ByteArrayInputStream(sparqlUpdate.getBytes()); 417 418 when(mockHttpclient.execute(any(HttpUriRequest.class))).thenThrow(new IOException("Expected error")); 419 420 try { 421 testClient.post(uri, body, SPARQL_UPDATE); 422 } catch (FcrepoOperationFailedException ex) { 423 assertEquals(ex.getUrl(), uri); 424 assertEquals(ex.getStatusText(), "Expected error"); 425 assertEquals(ex.getStatusCode(), -1); 426 } 427 } 428 429 @Test 430 public void testBadResponseBody() throws IOException, FcrepoOperationFailedException { 431 final int status = 200; 432 final URI uri = create(baseUrl); 433 final ByteArrayEntity entity = new ByteArrayEntity(rdfXml.getBytes()); 434 entity.setContentType(RDF_XML); 435 436 doSetupMockRequest(RDF_XML, entity, status); 437 when(mockResponse.getEntity()).thenReturn(mockEntity); 438 when(mockEntity.getContent()).thenThrow(new IOException("Expected IO error")); 439 440 final FcrepoResponse response = testClient.get(uri, RDF_XML, "return=minimal"); 441 442 assertEquals(response.getUrl(), uri); 443 assertEquals(response.getStatusCode(), status); 444 assertEquals(response.getContentType(), RDF_XML); 445 assertEquals(response.getLocation(), null); 446 assertEquals(response.getBody(), null); 447 } 448 449 private CloseableHttpResponse doSetupMockRequest(final String contentType, final ByteArrayEntity entity, 450 final int status) throws IOException { 451 return doSetupMockRequest(contentType, entity, status, null); 452 } 453 454 private CloseableHttpResponse doSetupMockRequest(final String contentType, final ByteArrayEntity entity, 455 final int status, final String statusPhrase) throws IOException { 456 final Header contentTypeHeader = new BasicHeader("Content-Type", contentType); 457 final Header[] linkHeaders = new Header[]{}; 458 final Header[] responseHeaders = new Header[]{ contentTypeHeader }; 459 460 when(mockHttpclient.execute(any(HttpUriRequest.class))).thenReturn(mockResponse); 461 when(mockResponse.getFirstHeader("location")).thenReturn(null); 462 when(mockResponse.getFirstHeader("Content-Type")).thenReturn(contentTypeHeader); 463 when(mockResponse.getHeaders("Link")).thenReturn(linkHeaders); 464 when(mockResponse.getEntity()).thenReturn(entity); 465 when(mockResponse.getStatusLine()).thenReturn(mockStatus); 466 when(mockStatus.getStatusCode()).thenReturn(status); 467 when(mockStatus.getReasonPhrase()).thenReturn(statusPhrase); 468 469 return mockResponse; 470 } 471}