Add test coverage (some failing) for DSTU2 ClientUtils
This commit is contained in:
parent
c5aaf43121
commit
a76078a5a5
|
@ -28,6 +28,12 @@
|
|||
<artifactId>org.hl7.fhir.utilities</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- UCUM -->
|
||||
<dependency>
|
||||
<groupId>org.fhir</groupId>
|
||||
|
@ -81,6 +87,24 @@
|
|||
</dependency>
|
||||
|
||||
<!-- Test dependencies -->
|
||||
<dependency>
|
||||
<groupId>org.assertj</groupId>
|
||||
<artifactId>assertj-core</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp3</groupId>
|
||||
<artifactId>mockwebserver</artifactId>
|
||||
<optional>true</optional>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.squareup.okio</groupId>
|
||||
<artifactId>okio</artifactId>
|
||||
<optional>true</optional>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
|
|
|
@ -48,6 +48,8 @@ import java.util.List;
|
|||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
@ -98,47 +100,37 @@ public class ClientUtils {
|
|||
public static final String HEADER_LOCATION = "location";
|
||||
private static boolean debugging = false;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private HttpHost proxy;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private int timeout = 5000;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private String username;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private String password;
|
||||
|
||||
@Setter
|
||||
@Getter
|
||||
private ToolingClientLogger logger;
|
||||
|
||||
@Setter
|
||||
@Getter
|
||||
private int retryCount;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private String userAgent;
|
||||
private String acceptLang;
|
||||
private String contentLang;
|
||||
|
||||
public HttpHost getProxy() {
|
||||
return proxy;
|
||||
}
|
||||
|
||||
public void setProxy(HttpHost proxy) {
|
||||
this.proxy = proxy;
|
||||
}
|
||||
|
||||
public int getTimeout() {
|
||||
return timeout;
|
||||
}
|
||||
|
||||
public void setTimeout(int timeout) {
|
||||
this.timeout = timeout;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
@Setter
|
||||
private String acceptLanguage;
|
||||
@Setter
|
||||
private String contentLanguage;
|
||||
|
||||
public <T extends Resource> ResourceRequest<T> issueOptionsRequest(URI optionsUri, String resourceFormat,
|
||||
int timeoutLoading) {
|
||||
|
@ -247,7 +239,6 @@ public class ClientUtils {
|
|||
|
||||
/**
|
||||
* @param resourceFormat
|
||||
* @param options
|
||||
* @return
|
||||
*/
|
||||
protected <T extends Resource> ResourceRequest<T> issueResourceRequest(String resourceFormat, HttpUriRequest request,
|
||||
|
@ -257,7 +248,6 @@ public class ClientUtils {
|
|||
|
||||
/**
|
||||
* @param resourceFormat
|
||||
* @param options
|
||||
* @return
|
||||
*/
|
||||
protected <T extends Resource> ResourceRequest<T> issueResourceRequest(String resourceFormat, HttpUriRequest request,
|
||||
|
@ -296,11 +286,11 @@ public class ClientUtils {
|
|||
if (!Utilities.noString(userAgent)) {
|
||||
request.addHeader("User-Agent", userAgent);
|
||||
}
|
||||
if (!Utilities.noString(acceptLang)) {
|
||||
request.addHeader("Accept-Language", acceptLang);
|
||||
if (!Utilities.noString(acceptLanguage)) {
|
||||
request.addHeader("Accept-Language", acceptLanguage);
|
||||
}
|
||||
if (!Utilities.noString(contentLang)) {
|
||||
request.addHeader("Content-Language", acceptLang);
|
||||
if (!Utilities.noString(contentLanguage)) {
|
||||
request.addHeader("Content-Language", acceptLanguage);
|
||||
}
|
||||
|
||||
if (format != null) {
|
||||
|
@ -363,9 +353,8 @@ public class ClientUtils {
|
|||
|
||||
/**
|
||||
*
|
||||
* @param request
|
||||
* @param payload
|
||||
* @return
|
||||
* @param request The request to be sent
|
||||
* @return The response from the server
|
||||
*/
|
||||
protected HttpResponse sendRequest(HttpUriRequest request) {
|
||||
if (FhirSettings.isProhibitNetworkAccess()) {
|
||||
|
@ -455,7 +444,7 @@ public class ClientUtils {
|
|||
return feed;
|
||||
}
|
||||
|
||||
private boolean hasError(OperationOutcome oo) {
|
||||
protected boolean hasError(OperationOutcome oo) {
|
||||
for (OperationOutcomeIssueComponent t : oo.getIssue())
|
||||
if (t.getSeverity() == IssueSeverity.ERROR || t.getSeverity() == IssueSeverity.FATAL)
|
||||
return true;
|
||||
|
@ -688,14 +677,6 @@ public class ClientUtils {
|
|||
return cnt;
|
||||
}
|
||||
|
||||
public ToolingClientLogger getLogger() {
|
||||
return logger;
|
||||
}
|
||||
|
||||
public void setLogger(ToolingClientLogger logger) {
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used for debugging
|
||||
*
|
||||
|
@ -714,26 +695,5 @@ public class ClientUtils {
|
|||
return value;
|
||||
}
|
||||
|
||||
public int getRetryCount() {
|
||||
return retryCount;
|
||||
}
|
||||
|
||||
public void setRetryCount(int retryCount) {
|
||||
this.retryCount = retryCount;
|
||||
}
|
||||
|
||||
public String getUserAgent() {
|
||||
return userAgent;
|
||||
}
|
||||
|
||||
public void setUserAgent(String userAgent) {
|
||||
this.userAgent = userAgent;
|
||||
}
|
||||
|
||||
public void setAcceptLanguage(String language) {
|
||||
this.acceptLang = language;
|
||||
}
|
||||
public void setContentLanguage(String language) {
|
||||
this.contentLang = language;
|
||||
}
|
||||
}
|
|
@ -355,170 +355,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
|
|||
return result.getPayload();
|
||||
}
|
||||
|
||||
//
|
||||
// public <T extends Resource> boolean delete(Class<T> resourceClass, String id) {
|
||||
// try {
|
||||
// return utils.issueDeleteRequest(resourceAddress.resolveGetUriFromResourceClassAndId(resourceClass, id), proxy);
|
||||
// } catch(Exception e) {
|
||||
// throw new EFhirClientException("An error has occurred while trying to delete this resource", e);
|
||||
// }
|
||||
//
|
||||
// }
|
||||
|
||||
//
|
||||
// public <T extends Resource> OperationOutcome create(Class<T> resourceClass, T resource) {
|
||||
// ResourceRequest<T> resourceRequest = null;
|
||||
// try {
|
||||
// List<Header> headers = null;
|
||||
// resourceRequest = utils.issuePostRequest(resourceAddress.resolveGetUriFromResourceClass(resourceClass),utils.getResourceAsByteArray(resource, false, isJson(getPreferredResourceFormat())), withVer(getPreferredResourceFormat(), "1.0"), headers, proxy);
|
||||
// resourceRequest.addSuccessStatus(201);
|
||||
// if(resourceRequest.isUnsuccessfulRequest()) {
|
||||
// throw new EFhirClientException("Server responded with HTTP error code " + resourceRequest.getHttpStatus(), (OperationOutcome)resourceRequest.getPayload());
|
||||
// }
|
||||
// } catch(Exception e) {
|
||||
// handleException("An error has occurred while trying to create this resource", e);
|
||||
// }
|
||||
// OperationOutcome operationOutcome = null;;
|
||||
// try {
|
||||
// operationOutcome = (OperationOutcome)resourceRequest.getPayload();
|
||||
// ResourceAddress.ResourceVersionedIdentifier resVersionedIdentifier =
|
||||
// ResourceAddress.parseCreateLocation(resourceRequest.getLocation());
|
||||
// OperationOutcomeIssueComponent issue = operationOutcome.addIssue();
|
||||
// issue.setSeverity(IssueSeverity.INFORMATION);
|
||||
// issue.setUserData(ResourceAddress.ResourceVersionedIdentifier.class.toString(),
|
||||
// resVersionedIdentifier);
|
||||
// return operationOutcome;
|
||||
// } catch(ClassCastException e) {
|
||||
// // some server (e.g. grahams) returns the resource directly
|
||||
// operationOutcome = new OperationOutcome();
|
||||
// OperationOutcomeIssueComponent issue = operationOutcome.addIssue();
|
||||
// issue.setSeverity(IssueSeverity.INFORMATION);
|
||||
// issue.setUserData(ResourceRequest.class.toString(),
|
||||
// resourceRequest.getPayload());
|
||||
// return operationOutcome;
|
||||
// }
|
||||
// }
|
||||
|
||||
//
|
||||
// public <T extends Resource> Bundle history(Calendar lastUpdate, Class<T> resourceClass, String id) {
|
||||
// Bundle history = null;
|
||||
// try {
|
||||
// history = utils.issueGetFeedRequest(resourceAddress.resolveGetHistoryForResourceId(resourceClass, id, lastUpdate, maxResultSetSize), withVer(getPreferredResourceFormat(), "1.0"), proxy);
|
||||
// } catch (Exception e) {
|
||||
// handleException("An error has occurred while trying to retrieve history information for this resource", e);
|
||||
// }
|
||||
// return history;
|
||||
// }
|
||||
|
||||
//
|
||||
// public <T extends Resource> Bundle history(Date lastUpdate, Class<T> resourceClass, String id) {
|
||||
// Bundle history = null;
|
||||
// try {
|
||||
// history = utils.issueGetFeedRequest(resourceAddress.resolveGetHistoryForResourceId(resourceClass, id, lastUpdate, maxResultSetSize), withVer(getPreferredResourceFormat(), "1.0"), proxy);
|
||||
// } catch (Exception e) {
|
||||
// handleException("An error has occurred while trying to retrieve history information for this resource", e);
|
||||
// }
|
||||
// return history;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// public <T extends Resource> Bundle history(Calendar lastUpdate, Class<T> resourceClass) {
|
||||
// Bundle history = null;
|
||||
// try {
|
||||
// history = utils.issueGetFeedRequest(resourceAddress.resolveGetHistoryForResourceType(resourceClass, lastUpdate, maxResultSetSize), withVer(getPreferredResourceFormat(), "1.0"), proxy);
|
||||
// } catch (Exception e) {
|
||||
// handleException("An error has occurred while trying to retrieve history information for this resource type", e);
|
||||
// }
|
||||
// return history;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// public <T extends Resource> Bundle history(Date lastUpdate, Class<T> resourceClass) {
|
||||
// Bundle history = null;
|
||||
// try {
|
||||
// history = utils.issueGetFeedRequest(resourceAddress.resolveGetHistoryForResourceType(resourceClass, lastUpdate, maxResultSetSize), withVer(getPreferredResourceFormat(), "1.0"), proxy);
|
||||
// } catch (Exception e) {
|
||||
// handleException("An error has occurred while trying to retrieve history information for this resource type", e);
|
||||
// }
|
||||
// return history;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// public <T extends Resource> Bundle history(Class<T> resourceClass) {
|
||||
// Bundle history = null;
|
||||
// try {
|
||||
// history = utils.issueGetFeedRequest(resourceAddress.resolveGetHistoryForResourceType(resourceClass, maxResultSetSize), withVer(getPreferredResourceFormat(), "1.0"), proxy);
|
||||
// } catch (Exception e) {
|
||||
// handleException("An error has occurred while trying to retrieve history information for this resource type", e);
|
||||
// }
|
||||
// return history;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// public <T extends Resource> Bundle history(Class<T> resourceClass, String id) {
|
||||
// Bundle history = null;
|
||||
// try {
|
||||
// history = utils.issueGetFeedRequest(resourceAddress.resolveGetHistoryForResourceId(resourceClass, id, maxResultSetSize), withVer(getPreferredResourceFormat(), "1.0"), proxy);
|
||||
// } catch (Exception e) {
|
||||
// handleException("An error has occurred while trying to retrieve history information for this resource", e);
|
||||
// }
|
||||
// return history;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// public <T extends Resource> Bundle history(Date lastUpdate) {
|
||||
// Bundle history = null;
|
||||
// try {
|
||||
// history = utils.issueGetFeedRequest(resourceAddress.resolveGetHistoryForAllResources(lastUpdate, maxResultSetSize), withVer(getPreferredResourceFormat(), "1.0"), proxy);
|
||||
// } catch (Exception e) {
|
||||
// handleException("An error has occurred while trying to retrieve history since last update",e);
|
||||
// }
|
||||
// return history;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// public <T extends Resource> Bundle history(Calendar lastUpdate) {
|
||||
// Bundle history = null;
|
||||
// try {
|
||||
// history = utils.issueGetFeedRequest(resourceAddress.resolveGetHistoryForAllResources(lastUpdate, maxResultSetSize), withVer(getPreferredResourceFormat(), "1.0"), proxy);
|
||||
// } catch (Exception e) {
|
||||
// handleException("An error has occurred while trying to retrieve history since last update",e);
|
||||
// }
|
||||
// return history;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// public <T extends Resource> Bundle history() {
|
||||
// Bundle history = null;
|
||||
// try {
|
||||
// history = utils.issueGetFeedRequest(resourceAddress.resolveGetHistoryForAllResources(maxResultSetSize), withVer(getPreferredResourceFormat(), "1.0"), proxy);
|
||||
// } catch (Exception e) {
|
||||
// handleException("An error has occurred while trying to retrieve history since last update",e);
|
||||
// }
|
||||
// return history;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// public <T extends Resource> Bundle search(Class<T> resourceClass, Map<String, String> parameters) {
|
||||
// Bundle searchResults = null;
|
||||
// try {
|
||||
// searchResults = utils.issueGetFeedRequest(resourceAddress.resolveSearchUri(resourceClass, parameters), withVer(getPreferredResourceFormat(), "1.0"), proxy);
|
||||
// } catch (Exception e) {
|
||||
// handleException("Error performing search with parameters " + parameters, e);
|
||||
// }
|
||||
// return searchResults;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// public <T extends Resource> Bundle searchPost(Class<T> resourceClass, T resource, Map<String, String> parameters) {
|
||||
// Bundle searchResults = null;
|
||||
// try {
|
||||
// searchResults = utils.issuePostFeedRequest(resourceAddress.resolveSearchUri(resourceClass, new HashMap<String, String>()), parameters, "src", resource, getPreferredResourceFormat());
|
||||
// } catch (Exception e) {
|
||||
// handleException("Error performing search with parameters " + parameters, e);
|
||||
// }
|
||||
// return searchResults;
|
||||
// }
|
||||
|
||||
public <T extends Resource> Parameters operateType(Class<T> resourceClass, String name, Parameters params) {
|
||||
recordUse();
|
||||
|
@ -588,101 +425,6 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
|
|||
return (OperationOutcome) result.getPayload();
|
||||
}
|
||||
|
||||
/*
|
||||
* change to meta operations
|
||||
*
|
||||
* public List<Coding> getAllTags() { TagListRequest result = null; try { result
|
||||
* = utils.issueGetRequestForTagList(resourceAddress.resolveGetAllTags(),
|
||||
* withVer(getPreferredResourceFormat(), "1.0"), null, proxy); } catch (Exception e) {
|
||||
* handleException("An error has occurred while trying to retrieve all tags",
|
||||
* e); } return result.getPayload(); }
|
||||
*
|
||||
*
|
||||
* public <T extends Resource> List<Coding> getAllTagsForResourceType(Class<T>
|
||||
* resourceClass) { TagListRequest result = null; try { result =
|
||||
* utils.issueGetRequestForTagList(resourceAddress.
|
||||
* resolveGetAllTagsForResourceType(resourceClass),
|
||||
* withVer(getPreferredResourceFormat(), "1.0"), null, proxy); } catch (Exception e) {
|
||||
* handleException("An error has occurred while trying to retrieve tags for this resource type"
|
||||
* , e); } return result.getPayload(); }
|
||||
*
|
||||
*
|
||||
* public <T extends Resource> List<Coding> getTagsForReference(Class<T>
|
||||
* resource, String id) { TagListRequest result = null; try { result =
|
||||
* utils.issueGetRequestForTagList(resourceAddress.resolveGetTagsForReference(
|
||||
* resource, id), withVer(getPreferredResourceFormat(), "1.0"), null, proxy); } catch (Exception
|
||||
* e) {
|
||||
* handleException("An error has occurred while trying to retrieve tags for this resource"
|
||||
* , e); } return result.getPayload(); }
|
||||
*
|
||||
*
|
||||
* public <T extends Resource> List<Coding> getTagsForResourceVersion(Class<T>
|
||||
* resource, String id, String versionId) { TagListRequest result = null; try {
|
||||
* result = utils.issueGetRequestForTagList(resourceAddress.
|
||||
* resolveGetTagsForResourceVersion(resource, id, versionId),
|
||||
* withVer(getPreferredResourceFormat(), "1.0"), null, proxy); } catch (Exception e) {
|
||||
* handleException("An error has occurred while trying to retrieve tags for this resource version"
|
||||
* , e); } return result.getPayload(); }
|
||||
*
|
||||
* // // public <T extends Resource> boolean deleteTagsForReference(Class<T>
|
||||
* resourceClass, String id) { // try { // return
|
||||
* utils.issueDeleteRequest(resourceAddress.resolveGetTagsForReference(
|
||||
* resourceClass, id), proxy); // } catch(Exception e) { //
|
||||
* handleException("An error has occurred while trying to retrieve tags for this resource version"
|
||||
* , e); // throw new
|
||||
* EFhirClientException("An error has occurred while trying to delete this resource"
|
||||
* , e); // } // // } // // // public <T extends Resource> boolean
|
||||
* deleteTagsForResourceVersion(Class<T> resourceClass, String id, List<Coding>
|
||||
* tags, String version) { // try { // return
|
||||
* utils.issueDeleteRequest(resourceAddress.resolveGetTagsForResourceVersion(
|
||||
* resourceClass, id, version), proxy); // } catch(Exception e) { //
|
||||
* handleException("An error has occurred while trying to retrieve tags for this resource version"
|
||||
* , e); // throw new
|
||||
* EFhirClientException("An error has occurred while trying to delete this resource"
|
||||
* , e); // } // }
|
||||
*
|
||||
*
|
||||
* public <T extends Resource> List<Coding> createTags(List<Coding> tags,
|
||||
* Class<T> resourceClass, String id) { TagListRequest request = null; try {
|
||||
* request =
|
||||
* utils.issuePostRequestForTagList(resourceAddress.resolveGetTagsForReference(
|
||||
* resourceClass, id),utils.getTagListAsByteArray(tags, false,
|
||||
* isJson(getPreferredResourceFormat())), withVer(getPreferredResourceFormat(), "1.0"), null,
|
||||
* proxy); request.addSuccessStatus(201); request.addSuccessStatus(200);
|
||||
* if(request.isUnsuccessfulRequest()) { throw new
|
||||
* EFhirClientException("Server responded with HTTP error code " +
|
||||
* request.getHttpStatus()); } } catch(Exception e) {
|
||||
* handleException("An error has occurred while trying to set tags for this resource"
|
||||
* , e); } return request.getPayload(); }
|
||||
*
|
||||
*
|
||||
* public <T extends Resource> List<Coding> createTags(List<Coding> tags,
|
||||
* Class<T> resourceClass, String id, String version) { TagListRequest request =
|
||||
* null; try { request = utils.issuePostRequestForTagList(resourceAddress.
|
||||
* resolveGetTagsForResourceVersion(resourceClass, id,
|
||||
* version),utils.getTagListAsByteArray(tags, false,
|
||||
* isJson(getPreferredResourceFormat())), withVer(getPreferredResourceFormat(), "1.0"), null,
|
||||
* proxy); request.addSuccessStatus(201); request.addSuccessStatus(200);
|
||||
* if(request.isUnsuccessfulRequest()) { throw new
|
||||
* EFhirClientException("Server responded with HTTP error code " +
|
||||
* request.getHttpStatus()); } } catch(Exception e) {
|
||||
* handleException("An error has occurred while trying to set the tags for this resource version"
|
||||
* , e); } return request.getPayload(); }
|
||||
*
|
||||
*
|
||||
* public <T extends Resource> List<Coding> deleteTags(List<Coding> tags,
|
||||
* Class<T> resourceClass, String id, String version) { TagListRequest request =
|
||||
* null; try { request = utils.issuePostRequestForTagList(resourceAddress.
|
||||
* resolveDeleteTagsForResourceVersion(resourceClass, id,
|
||||
* version),utils.getTagListAsByteArray(tags, false,
|
||||
* isJson(getPreferredResourceFormat())), withVer(getPreferredResourceFormat(), "1.0"), null,
|
||||
* proxy); request.addSuccessStatus(201); request.addSuccessStatus(200);
|
||||
* if(request.isUnsuccessfulRequest()) { throw new
|
||||
* EFhirClientException("Server responded with HTTP error code " +
|
||||
* request.getHttpStatus()); } } catch(Exception e) {
|
||||
* handleException("An error has occurred while trying to delete the tags for this resource version"
|
||||
* , e); } return request.getPayload(); }
|
||||
*/
|
||||
|
||||
/**
|
||||
* Helper method to prevent nesting of previously thrown EFhirClientExceptions
|
||||
|
|
|
@ -32,11 +32,15 @@ package org.hl7.fhir.dstu2.utils.client;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import lombok.Getter;
|
||||
import org.hl7.fhir.dstu2.model.Resource;
|
||||
|
||||
public class ResourceRequest<T extends Resource> {
|
||||
@Getter
|
||||
private T payload;
|
||||
@Getter
|
||||
private int httpStatus = -1;
|
||||
@Getter
|
||||
private String location;
|
||||
private List<Integer> successfulStatuses = new ArrayList<Integer>();
|
||||
private List<Integer> errorStatuses = new ArrayList<Integer>();
|
||||
|
@ -67,14 +71,6 @@ public class ResourceRequest<T extends Resource> {
|
|||
this.location = location;
|
||||
}
|
||||
|
||||
public int getHttpStatus() {
|
||||
return httpStatus;
|
||||
}
|
||||
|
||||
public T getPayload() {
|
||||
return payload;
|
||||
}
|
||||
|
||||
public T getReference() {
|
||||
T payloadResource = null;
|
||||
if (payload != null) {
|
||||
|
@ -99,7 +95,4 @@ public class ResourceRequest<T extends Resource> {
|
|||
this.errorStatuses.add(status);
|
||||
}
|
||||
|
||||
public String getLocation() {
|
||||
return location;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,330 @@
|
|||
package org.hl7.fhir.dstu2.utils.client;
|
||||
|
||||
|
||||
import okhttp3.HttpUrl;
|
||||
import okhttp3.mockwebserver.MockResponse;
|
||||
import okhttp3.mockwebserver.MockWebServer;
|
||||
import okhttp3.mockwebserver.RecordedRequest;
|
||||
import org.hl7.fhir.dstu2.formats.JsonParser;
|
||||
import org.hl7.fhir.dstu2.model.*;
|
||||
import org.hl7.fhir.utilities.ToolingClientLogger;
|
||||
import org.hl7.fhir.utilities.http.HTTPHeader;
|
||||
import org.hl7.fhir.utilities.http.HTTPHeaderUtil;
|
||||
import org.hl7.fhir.utilities.http.HTTPRequest;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
public class ClientUtilsTest {
|
||||
|
||||
public static final String DUMMY_LOCATION = "http://myhost/Patient/1";
|
||||
public static final int TIMEOUT = 5000;
|
||||
private MockWebServer server;
|
||||
private HttpUrl serverUrl;
|
||||
private ClientUtils clientUtils;
|
||||
|
||||
private final Address address = new Address()
|
||||
.setCity("Toronto")
|
||||
.setState("Ontario")
|
||||
.setCountry("Canada");
|
||||
private final HumanName humanName = new HumanName()
|
||||
.addGiven("Mark")
|
||||
.addFamily("Iantorno");
|
||||
private final Patient patient = new Patient()
|
||||
.addName(humanName)
|
||||
.addAddress(address)
|
||||
.setGender(Enumerations.AdministrativeGender.MALE);
|
||||
|
||||
@BeforeEach
|
||||
void setup() {
|
||||
setupMockServer();
|
||||
clientUtils = new ClientUtils();
|
||||
}
|
||||
|
||||
void setupMockServer() {
|
||||
server = new MockWebServer();
|
||||
serverUrl = server.url("/v1/endpoint");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test resource format headers are added correctly.")
|
||||
void addResourceFormatHeadersGET() {
|
||||
/* FIXME restore this after refactor
|
||||
String testFormat = "yaml";
|
||||
HTTPRequest request = new HTTPRequest().withUrl("http://www.google.com").withMethod(HTTPRequest.HttpMethod.GET);
|
||||
|
||||
Iterable<HTTPHeader> headers = FhirRequestBuilder.getResourceFormatHeaders(request, testFormat);
|
||||
|
||||
Map<String, List<String>> headersMap = HTTPHeaderUtil.getMultimap(headers);
|
||||
Assertions.assertNotNull(headersMap.get("Accept"), "Accept header null.");
|
||||
Assertions.assertEquals(testFormat, headersMap.get("Accept").get(0),
|
||||
"Accept header not populated with expected value " + testFormat + ".");
|
||||
|
||||
Assertions.assertNull(headersMap.get("Content-Type"), "Content-Type header null.");
|
||||
|
||||
*/
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test resource format headers are added correctly (POST).")
|
||||
void addResourceFormatHeadersPOST() {
|
||||
/*FIXME restore this after refactor
|
||||
String testFormat = "yaml";
|
||||
HTTPRequest request = new HTTPRequest().withUrl("http://www.google.com").withMethod(HTTPRequest.HttpMethod.POST);
|
||||
|
||||
Iterable<HTTPHeader> headers = FhirRequestBuilder.getResourceFormatHeaders(request, testFormat);
|
||||
|
||||
Map<String, List<String>> headersMap = HTTPHeaderUtil.getMultimap(headers);
|
||||
Assertions.assertNotNull(headersMap.get("Accept"), "Accept header null.");
|
||||
Assertions.assertEquals(testFormat, headersMap.get("Accept").get(0),
|
||||
"Accept header not populated with expected value " + testFormat + ".");
|
||||
|
||||
Assertions.assertNotNull(headersMap.get("Content-Type"), "Content-Type header null.");
|
||||
Assertions.assertEquals(testFormat + ";charset=" + FhirRequestBuilder.DEFAULT_CHARSET, headersMap.get("Content-Type").get(0),
|
||||
"Content-Type header not populated with expected value \"" + testFormat + ";charset=" + FhirRequestBuilder.DEFAULT_CHARSET + "\".");
|
||||
|
||||
*/
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResourceFormat() {
|
||||
ResourceFormat format = ResourceFormat.RESOURCE_XML;
|
||||
assertThat(format.getHeader()).isEqualTo("application/xml+fhir");
|
||||
format = ResourceFormat.RESOURCE_JSON;
|
||||
assertThat(format.getHeader()).isEqualTo("application/json+fhir");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResourceRequest() {
|
||||
ResourceRequest<Patient> request = new ResourceRequest<>(new Patient(), 200, "location");
|
||||
request.addSuccessStatus(200);
|
||||
assertTrue(request.getPayload().equalsDeep(new Patient()));
|
||||
assertThat(request.getHttpStatus()).isEqualTo(200);
|
||||
assertThat(request.getLocation()).isEqualTo("location");
|
||||
assertTrue(request.isSuccessfulRequest());
|
||||
assertFalse(request.isUnsuccessfulRequest());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIssueGetResourceRequest() throws IOException {
|
||||
server.enqueue(
|
||||
new MockResponse()
|
||||
.setBody(new String(generateResourceBytes(patient)))
|
||||
.addHeader("Content-Type", "application/json+fhir")
|
||||
.addHeader("Location", DUMMY_LOCATION)
|
||||
);
|
||||
ResourceRequest<Patient> resourceRequest = clientUtils.issueGetResourceRequest(serverUrl.uri(), "application/json+fhir", TIMEOUT);
|
||||
resourceRequest.addSuccessStatus(200);
|
||||
assertThat(resourceRequest.getLocation()).isEqualTo(DUMMY_LOCATION);
|
||||
assertTrue(resourceRequest.isSuccessfulRequest());
|
||||
assertTrue(patient.equalsDeep(resourceRequest.getPayload()));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testIssueGetResourceRequest_withContentLocation() throws IOException {
|
||||
server.enqueue(
|
||||
new MockResponse()
|
||||
.setBody(new String(generateResourceBytes(patient)))
|
||||
.addHeader("Content-Type", "application/json+fhir")
|
||||
.addHeader("Content-Location", DUMMY_LOCATION)
|
||||
);
|
||||
ResourceRequest<Patient> resourceRequest = clientUtils.issueGetResourceRequest(serverUrl.uri(), "application/json+fhir", TIMEOUT);
|
||||
resourceRequest.addSuccessStatus(200);
|
||||
assertThat(resourceRequest.getLocation()).isEqualTo(DUMMY_LOCATION);
|
||||
assertTrue(resourceRequest.isSuccessfulRequest());
|
||||
assertTrue(patient.equalsDeep(resourceRequest.getPayload()));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test that getLocationHeader returns 'location' header when both 'location' and 'content-location' are set.")
|
||||
void testIssueGetResourceRequest_ReturnsLocationHeaderWhenBothSet() throws IOException {
|
||||
server.enqueue(
|
||||
new MockResponse()
|
||||
.setBody(new String(generateResourceBytes(patient)))
|
||||
.addHeader("Content-Type", "application/json+fhir")
|
||||
.addHeader("Location", DUMMY_LOCATION)
|
||||
.addHeader("Content-Location", "Wrong wrong wrong")
|
||||
);
|
||||
ResourceRequest<Patient> resourceRequest = clientUtils.issueGetResourceRequest(serverUrl.uri(), "application/json+fhir", TIMEOUT);
|
||||
resourceRequest.addSuccessStatus(200);
|
||||
assertThat(resourceRequest.getLocation()).isEqualTo(DUMMY_LOCATION);
|
||||
assertTrue(resourceRequest.isSuccessfulRequest());
|
||||
assertTrue(patient.equalsDeep(resourceRequest.getPayload()));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test that getLocationHeader returns 'null' header when neither 'location' or 'content-location' are set.")
|
||||
void testIssueGetResourceRequest_ReturnsNullWhenNoHeadersSet() throws IOException {
|
||||
server.enqueue(
|
||||
new MockResponse()
|
||||
.setBody(new String(generateResourceBytes(patient)))
|
||||
.addHeader("Content-Type", "application/json+fhir")
|
||||
);
|
||||
ResourceRequest<Patient> resourceRequest = clientUtils.issueGetResourceRequest(serverUrl.uri(), "application/json+fhir", TIMEOUT);
|
||||
resourceRequest.addSuccessStatus(200);
|
||||
assertThat(resourceRequest.getLocation()).isNull();
|
||||
assertTrue(resourceRequest.isSuccessfulRequest());
|
||||
assertTrue(patient.equalsDeep(resourceRequest.getPayload()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIssuePostRequest() throws IOException, InterruptedException {
|
||||
byte[] payload = generateResourceBytes(patient);
|
||||
server.enqueue(
|
||||
new MockResponse().setBody(new String(payload)).addHeader("Content-Type", "application/json+fhir").addHeader("Location", DUMMY_LOCATION).setResponseCode(201)
|
||||
);
|
||||
ResourceRequest<Patient> resourceRequest = clientUtils.issuePostRequest(serverUrl.uri(), payload, "application/json+fhir", TIMEOUT);
|
||||
resourceRequest.addSuccessStatus(201);
|
||||
|
||||
RecordedRequest recordedRequest = server.takeRequest();
|
||||
assertArrayEquals(payload, recordedRequest.getBody().readByteArray(),
|
||||
"PUT request payload does not match send data.");
|
||||
assertThat(resourceRequest.getLocation()).isEqualTo(DUMMY_LOCATION);
|
||||
assertTrue(resourceRequest.isSuccessfulRequest());
|
||||
assertTrue(patient.equalsDeep(resourceRequest.getPayload()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIssuePutRequest() throws IOException, InterruptedException {
|
||||
byte[] payload = generateResourceBytes(patient);
|
||||
server.enqueue(
|
||||
new MockResponse().setBody(new String(payload)).addHeader("Content-Type", "application/json+fhir").addHeader("Location", DUMMY_LOCATION).setResponseCode(200)
|
||||
);
|
||||
ResourceRequest<Patient> resourceRequest = clientUtils.issuePutRequest(serverUrl.uri(), payload, "application/json+fhir", TIMEOUT);
|
||||
resourceRequest.addSuccessStatus(200);
|
||||
RecordedRequest recordedRequest = server.takeRequest();
|
||||
assertArrayEquals(payload, recordedRequest.getBody().readByteArray(),
|
||||
"PUT request payload does not match send data.");
|
||||
|
||||
assertThat(resourceRequest.getLocation()).isEqualTo(DUMMY_LOCATION);
|
||||
assertTrue(resourceRequest.isSuccessfulRequest());
|
||||
assertTrue(patient.equalsDeep(resourceRequest.getPayload()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIssueDeleteRequest() throws IOException {
|
||||
server.enqueue(
|
||||
new MockResponse().addHeader("Location", DUMMY_LOCATION).setResponseCode(204)
|
||||
);
|
||||
boolean success = clientUtils.issueDeleteRequest(serverUrl.uri());
|
||||
assertTrue(success);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIssueDeleteRequest_fail() throws IOException, InterruptedException {
|
||||
server.enqueue(
|
||||
new MockResponse().addHeader("Location", DUMMY_LOCATION).setResponseCode(500)
|
||||
);
|
||||
boolean success = clientUtils.issueDeleteRequest(serverUrl.uri());
|
||||
RecordedRequest recordedRequest = server.takeRequest();
|
||||
assertThat(recordedRequest.getMethod()).isEqualTo("DELETE");
|
||||
assertThat(recordedRequest.getRequestUrl().uri()).isEqualTo(serverUrl.uri());
|
||||
assertFalse(success);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("test logger works")
|
||||
public void testLogger() throws IOException, InterruptedException {
|
||||
byte[] payload = generateResourceBytes(patient);
|
||||
server.enqueue(
|
||||
new MockResponse()
|
||||
.setResponseCode(200)
|
||||
.setBody(new String(payload))
|
||||
);
|
||||
ToolingClientLogger mockLogger = Mockito.mock(ToolingClientLogger.class);
|
||||
clientUtils.setLogger(mockLogger);
|
||||
clientUtils.issuePostRequest(serverUrl.uri(), payload, "application/json+fhir"
|
||||
, null, TIMEOUT);
|
||||
server.takeRequest();
|
||||
Mockito.verify(mockLogger, Mockito.times(1))
|
||||
.logRequest(Mockito.anyString(), Mockito.anyString(), Mockito.anyList(), Mockito.any());
|
||||
Mockito.verify(mockLogger, Mockito.times(1))
|
||||
.logResponse(Mockito.anyString(), Mockito.anyList(), Mockito.any(), Mockito.anyLong());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test that FATAL issue severity triggers error.")
|
||||
void hasErrorTestFatal() {
|
||||
OperationOutcome outcome = new OperationOutcome();
|
||||
outcome.addIssue(new OperationOutcome.OperationOutcomeIssueComponent().setSeverity(OperationOutcome.IssueSeverity.INFORMATION));
|
||||
outcome.addIssue(new OperationOutcome.OperationOutcomeIssueComponent().setSeverity(OperationOutcome.IssueSeverity.NULL));
|
||||
outcome.addIssue(new OperationOutcome.OperationOutcomeIssueComponent().setSeverity(OperationOutcome.IssueSeverity.WARNING));
|
||||
outcome.addIssue(new OperationOutcome.OperationOutcomeIssueComponent().setSeverity(OperationOutcome.IssueSeverity.FATAL));
|
||||
Assertions.assertTrue(clientUtils.hasError(outcome), "Error check not triggered for FATAL issue severity.");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test that ERROR issue severity triggers error.")
|
||||
void hasErrorTestError() {
|
||||
OperationOutcome outcome = new OperationOutcome();
|
||||
outcome.addIssue(new OperationOutcome.OperationOutcomeIssueComponent().setSeverity(OperationOutcome.IssueSeverity.INFORMATION));
|
||||
outcome.addIssue(new OperationOutcome.OperationOutcomeIssueComponent().setSeverity(OperationOutcome.IssueSeverity.NULL));
|
||||
outcome.addIssue(new OperationOutcome.OperationOutcomeIssueComponent().setSeverity(OperationOutcome.IssueSeverity.WARNING));
|
||||
outcome.addIssue(new OperationOutcome.OperationOutcomeIssueComponent().setSeverity(OperationOutcome.IssueSeverity.ERROR));
|
||||
Assertions.assertTrue(clientUtils.hasError(outcome), "Error check not triggered for ERROR issue severity.");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test that no FATAL or ERROR issue severity does not trigger error.")
|
||||
void hasErrorTestNoErrors() {
|
||||
OperationOutcome outcome = new OperationOutcome();
|
||||
outcome.addIssue(new OperationOutcome.OperationOutcomeIssueComponent().setSeverity(OperationOutcome.IssueSeverity.INFORMATION));
|
||||
outcome.addIssue(new OperationOutcome.OperationOutcomeIssueComponent().setSeverity(OperationOutcome.IssueSeverity.NULL));
|
||||
outcome.addIssue(new OperationOutcome.OperationOutcomeIssueComponent().setSeverity(OperationOutcome.IssueSeverity.WARNING));
|
||||
Assertions.assertFalse(clientUtils.hasError(outcome), "Error check triggered unexpectedly.");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("GET request, test client retries after timeout failure.")
|
||||
void test_get_retries_with_timeout() throws IOException, URISyntaxException {
|
||||
int failedAttempts = new Random().nextInt(5) + 1;
|
||||
System.out.println("Simulating <" + failedAttempts + "> failed connections (timeouts) before success.");
|
||||
for (int i = 0; i < failedAttempts; i++) {
|
||||
server.enqueue(new MockResponse().setHeadersDelay(TIMEOUT * 10, TimeUnit.MILLISECONDS)
|
||||
.setBody(new String(generateResourceBytes(patient))));
|
||||
}
|
||||
server.enqueue(new MockResponse().setBody(new String(generateResourceBytes(patient))));
|
||||
clientUtils.setRetryCount(failedAttempts + 1);
|
||||
|
||||
ResourceRequest<Resource> resourceRequest = clientUtils.issueGetResourceRequest(serverUrl.uri(), "application/json+fhir"
|
||||
, TIMEOUT);
|
||||
Assertions.assertTrue(resourceRequest.isSuccessfulRequest());
|
||||
Assertions.assertTrue(patient.equalsDeep(resourceRequest.getPayload()),
|
||||
"GET request returned resource does not match expected.");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("GET request, test client retries after bad response.")
|
||||
void test_get_retries_with_unsuccessful_response() throws IOException, URISyntaxException {
|
||||
int failedAttempts = new Random().nextInt(5) + 1;
|
||||
System.out.println("Simulating <" + failedAttempts + "> failed connections (bad response codes) before success.");
|
||||
for (int i = 0; i < failedAttempts; i++) {
|
||||
server.enqueue(new MockResponse().setResponseCode(400 + i).setBody(new String(generateResourceBytes(patient))));
|
||||
}
|
||||
server.enqueue(new MockResponse().setBody(new String(generateResourceBytes(patient))));
|
||||
clientUtils.setRetryCount(failedAttempts + 1);
|
||||
|
||||
ResourceRequest<Resource> resourceRequest = clientUtils.issueGetResourceRequest(serverUrl.uri(), "application/json+fhir", TIMEOUT);
|
||||
Assertions.assertTrue(resourceRequest.isSuccessfulRequest());
|
||||
Assertions.assertTrue(patient.equalsDeep(resourceRequest.getPayload()),
|
||||
"GET request returned resource does not match expected.");
|
||||
}
|
||||
|
||||
|
||||
byte[] generateResourceBytes(Resource resource) throws IOException {
|
||||
return new JsonParser().composeBytes(resource);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue