Skip to content

Commit

Permalink
Added R4 to the client's server version check. Also tweaked the Clien…
Browse files Browse the repository at this point in the history
…tServerValidation* tests to be a little more predictable
  • Loading branch information
InfiniteLoop90 committed Aug 13, 2017
1 parent 04f1629 commit 9a6f4f8
Show file tree
Hide file tree
Showing 6 changed files with 388 additions and 70 deletions.
Expand Up @@ -330,6 +330,8 @@ public void validateServerBase(String theServerBase, IHttpClient theHttpClient,
serverFhirVersionEnum = FhirVersionEnum.DSTU2_1;
} else if (serverFhirVersionString.equals(FhirVersionEnum.DSTU3.getFhirVersionString())) {
serverFhirVersionEnum = FhirVersionEnum.DSTU3;
} else if (serverFhirVersionString.equals(FhirVersionEnum.R4.getFhirVersionString())) {
serverFhirVersionEnum = FhirVersionEnum.R4;
} else {
// we'll be lenient and accept this
ourLog.debug("Server conformance statement indicates unknown FHIR version: {}", serverFhirVersionString);
Expand Down
@@ -0,0 +1,152 @@
package ca.uhn.fhir.rest.client;

import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import java.io.InputStream;
import java.io.StringReader;
import java.nio.charset.Charset;

import ca.uhn.fhir.context.FhirVersionEnum;
import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.client.api.IGenericClient;
import ca.uhn.fhir.rest.client.api.ServerValidationModeEnum;
import org.apache.commons.io.input.ReaderInputStream;
import org.apache.http.HttpResponse;
import org.apache.http.ProtocolVersion;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicStatusLine;
import org.hl7.fhir.dstu2016may.model.Conformance;
import org.hl7.fhir.dstu2016may.model.Patient;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Matchers;
import org.mockito.internal.stubbing.defaultanswers.ReturnsDeepStubs;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;

import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.primitive.UriDt;
import ca.uhn.fhir.rest.client.exceptions.FhirClientInappropriateForServerException;
import ca.uhn.fhir.util.TestUtil;

public class ClientServerValidationDstu2_1Test {

private FhirContext myCtx;
private HttpClient myHttpClient;
private HttpResponse myHttpResponse;
private boolean myFirstResponse;

@Before
public void before() {
myHttpClient = mock(HttpClient.class, new ReturnsDeepStubs());
myHttpResponse = mock(HttpResponse.class, new ReturnsDeepStubs());
myFirstResponse = true;

myCtx = FhirContext.forDstu2_1();
myCtx.getRestfulClientFactory().setHttpClient(myHttpClient);
}

@Test
public void testServerReturnsAppropriateVersionDstu2_1() throws Exception {
String appropriateFhirVersion = "1.4.0";
assertThat(appropriateFhirVersion, is(FhirVersionEnum.DSTU2_1.getFhirVersionString()));
Conformance conf = new Conformance();
conf.setFhirVersion(appropriateFhirVersion);
final String confResource = myCtx.newXmlParser().encodeResourceToString(conf);

ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);

when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<InputStream>() {
@Override
public InputStream answer(InvocationOnMock theInvocation) throws Throwable {
if (myFirstResponse) {
myFirstResponse=false;
return new ReaderInputStream(new StringReader(confResource), Charset.forName("UTF-8"));
} else {
return new ReaderInputStream(new StringReader(myCtx.newXmlParser().encodeResourceToString(new Patient())), Charset.forName("UTF-8"));
}
}});

when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);

myCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.ONCE);
IGenericClient client = myCtx.newRestfulGenericClient("http://foo");

// don't load the conformance until the first time the client is actually used
assertTrue(myFirstResponse);
client.read(new UriDt("http://foo/Patient/123"));
assertFalse(myFirstResponse);
myCtx.newRestfulGenericClient("http://foo").read(new UriDt("http://foo/Patient/123"));
myCtx.newRestfulGenericClient("http://foo").read(new UriDt("http://foo/Patient/123"));

// Conformance only loaded once, then 3 reads
verify(myHttpClient, times(4)).execute(Matchers.any(HttpUriRequest.class));
}

@Test
public void testServerReturnsWrongVersionDstu2_1() throws Exception {
String wrongFhirVersion = "1.0.2";
assertThat(wrongFhirVersion, is(FhirVersionEnum.DSTU2.getFhirVersionString()));
Conformance conf = new Conformance();
conf.setFhirVersion(wrongFhirVersion);
String msg = myCtx.newXmlParser().encodeResourceToString(conf);

ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);

when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8")));

when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);

myCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.ONCE);
try {
myCtx.newRestfulGenericClient("http://foo").read(new UriDt("http://foo/Patient/1"));
fail();
} catch (FhirClientInappropriateForServerException e) {
assertThat(e.toString(), containsString("The server at base URL \"http://foo/metadata\" returned a conformance statement indicating that it supports FHIR version \"1.0.2\" which corresponds to DSTU2, but this client is configured to use DSTU2_1 (via the FhirContext)"));
}
}

@Test
public void testServerReturnsRightVersionDstu2_1() throws Exception {
String appropriateFhirVersion = "1.4.0";
assertThat(appropriateFhirVersion, is(FhirVersionEnum.DSTU2_1.getFhirVersionString()));
Conformance conf = new Conformance();
conf.setFhirVersion(appropriateFhirVersion);
String msg = myCtx.newXmlParser().encodeResourceToString(conf);

ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);

when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenReturn(new ReaderInputStream(new StringReader(msg), Charset.forName("UTF-8")));

when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);

myCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.ONCE);
myCtx.newRestfulGenericClient("http://foo").forceConformanceCheck();
}

@AfterClass
public static void afterClassClearContext() {
TestUtil.clearAllStaticFieldsForUnitTest();
}

}

@@ -1,6 +1,7 @@
package ca.uhn.fhir.rest.client;

import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
Expand All @@ -16,6 +17,7 @@
import java.io.StringReader;
import java.nio.charset.Charset;

import ca.uhn.fhir.context.FhirVersionEnum;
import org.apache.commons.io.input.ReaderInputStream;
import org.apache.http.*;
import org.apache.http.client.HttpClient;
Expand Down Expand Up @@ -67,8 +69,10 @@ public void before() {

@Test
public void testClientUsesInterceptors() throws Exception {
String appropriateFhirVersion = "1.0.2";
assertThat(appropriateFhirVersion, is(FhirVersionEnum.DSTU2.getFhirVersionString()));
Conformance conf = new Conformance();
conf.setFhirVersion("1.0.2");
conf.setFhirVersion(appropriateFhirVersion);
final String confResource = myCtx.newXmlParser().encodeResourceToString(conf);

ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
Expand Down Expand Up @@ -109,8 +113,10 @@ public InputStream answer(InvocationOnMock theInvocation) throws Throwable {

@Test
public void testForceConformanceCheck() throws Exception {
String appropriateFhirVersion = "1.0.2";
assertThat(appropriateFhirVersion, is(FhirVersionEnum.DSTU2.getFhirVersionString()));
Conformance conf = new Conformance();
conf.setFhirVersion("1.0.2");
conf.setFhirVersion(appropriateFhirVersion);
final String confResource = myCtx.newXmlParser().encodeResourceToString(conf);

ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
Expand Down Expand Up @@ -178,46 +184,9 @@ public InputStream answer(InvocationOnMock theInvocation) throws Throwable {
}
}

// This test can should stay to test the leniency of accepting unknown FHIR versions from the server
@Test
public void testServerReturnsAppropriateVersionForDstu2_040() throws Exception {
Conformance conf = new Conformance();
conf.setFhirVersion("0.5.0");
final String confResource = myCtx.newXmlParser().encodeResourceToString(conf);

ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);

when(myHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), 200, "OK"));
when(myHttpResponse.getEntity().getContentType()).thenReturn(new BasicHeader("content-type", Constants.CT_FHIR_XML + "; charset=UTF-8"));
when(myHttpResponse.getEntity().getContent()).thenAnswer(new Answer<InputStream>() {
@Override
public InputStream answer(InvocationOnMock theInvocation) throws Throwable {
if (myFirstResponse) {
myFirstResponse = false;
return new ReaderInputStream(new StringReader(confResource), Charset.forName("UTF-8"));
} else {
return new ReaderInputStream(new StringReader(myCtx.newXmlParser().encodeResourceToString(new Patient())), Charset.forName("UTF-8"));
}
}
});

when(myHttpClient.execute(capt.capture())).thenReturn(myHttpResponse);

myCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.ONCE);
IGenericClient client = myCtx.newRestfulGenericClient("http://foo");

// don't load the conformance until the first time the client is actually used
assertTrue(myFirstResponse);
client.read(new UriDt("http://foo/Patient/123"));
assertFalse(myFirstResponse);
myCtx.newRestfulGenericClient("http://foo").read(new UriDt("http://foo/Patient/123"));
myCtx.newRestfulGenericClient("http://foo").read(new UriDt("http://foo/Patient/123"));

// Conformance only loaded once, then 3 reads
verify(myHttpClient, times(4)).execute(Matchers.any(HttpUriRequest.class));
}

@Test
public void testServerReturnsAppropriateVersionForDstu2_050() throws Exception {
public void testServerReturnsAppropriateVersionForUnknownVersion() throws Exception {
Conformance conf = new Conformance();
conf.setFhirVersion("0.5.0");
final String confResource = myCtx.newXmlParser().encodeResourceToString(conf);
Expand Down Expand Up @@ -256,8 +225,10 @@ public InputStream answer(InvocationOnMock theInvocation) throws Throwable {

@Test
public void testServerReturnsAppropriateVersionForDstu2() throws Exception {
String appropriateFhirVersion = "1.0.2";
assertThat(appropriateFhirVersion, is(FhirVersionEnum.DSTU2.getFhirVersionString()));
Conformance conf = new Conformance();
conf.setFhirVersion("1.0.2");
conf.setFhirVersion(appropriateFhirVersion);
final String confResource = myCtx.newXmlParser().encodeResourceToString(conf);

ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
Expand Down Expand Up @@ -294,8 +265,10 @@ public InputStream answer(InvocationOnMock theInvocation) throws Throwable {

@Test
public void testServerReturnsWrongVersionForDstu2() throws Exception {
String wrongFhirVersion = "3.0.1";
assertThat(wrongFhirVersion, is(FhirVersionEnum.DSTU3.getFhirVersionString())); // asserting that what we assume to be the DSTU3 FHIR version is still correct
Conformance conf = new Conformance();
conf.setFhirVersion("3.0.1");
conf.setFhirVersion(wrongFhirVersion);
String msg = myCtx.newXmlParser().encodeResourceToString(conf);

ArgumentCaptor<HttpUriRequest> capt = ArgumentCaptor.forClass(HttpUriRequest.class);
Expand Down

0 comments on commit 9a6f4f8

Please sign in to comment.