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