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