Merge pull request #1600 from jamesagnew/ks-20191122-fix-include-circular-ref

fix circular reference include everything
This commit is contained in:
Ken Stevens 2019-11-22 12:55:37 -05:00 committed by GitHub
commit f7f1ec26bc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 158 additions and 99 deletions

View File

@ -20,15 +20,7 @@ package ca.uhn.fhir.jpa.dao;
* #L% * #L%
*/ */
import ca.uhn.fhir.context.BaseRuntimeChildDefinition; import ca.uhn.fhir.context.*;
import ca.uhn.fhir.context.BaseRuntimeDeclaredChildDefinition;
import ca.uhn.fhir.context.BaseRuntimeElementDefinition;
import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.RuntimeChildChoiceDefinition;
import ca.uhn.fhir.context.RuntimeChildResourceDefinition;
import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.context.RuntimeSearchParam;
import ca.uhn.fhir.interceptor.api.HookParams; import ca.uhn.fhir.interceptor.api.HookParams;
import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster; import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster;
import ca.uhn.fhir.interceptor.api.Pointcut; import ca.uhn.fhir.interceptor.api.Pointcut;
@ -51,18 +43,8 @@ import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
import ca.uhn.fhir.jpa.searchparam.util.SourceParam; import ca.uhn.fhir.jpa.searchparam.util.SourceParam;
import ca.uhn.fhir.jpa.term.VersionIndependentConcept; import ca.uhn.fhir.jpa.term.VersionIndependentConcept;
import ca.uhn.fhir.jpa.term.api.ITermReadSvc; import ca.uhn.fhir.jpa.term.api.ITermReadSvc;
import ca.uhn.fhir.jpa.util.BaseIterator; import ca.uhn.fhir.jpa.util.*;
import ca.uhn.fhir.jpa.util.CurrentThreadCaptureQueriesListener; import ca.uhn.fhir.model.api.*;
import ca.uhn.fhir.jpa.util.JpaInterceptorBroadcaster;
import ca.uhn.fhir.jpa.util.ScrollableResultsIterator;
import ca.uhn.fhir.jpa.util.SqlQueryList;
import ca.uhn.fhir.model.api.IPrimitiveDatatype;
import ca.uhn.fhir.model.api.IQueryParameterAnd;
import ca.uhn.fhir.model.api.IQueryParameterOr;
import ca.uhn.fhir.model.api.IQueryParameterType;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.Include;
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
import ca.uhn.fhir.model.base.composite.BaseCodingDt; import ca.uhn.fhir.model.base.composite.BaseCodingDt;
import ca.uhn.fhir.model.base.composite.BaseIdentifierDt; import ca.uhn.fhir.model.base.composite.BaseIdentifierDt;
import ca.uhn.fhir.model.base.composite.BaseQuantityDt; import ca.uhn.fhir.model.base.composite.BaseQuantityDt;
@ -70,11 +52,7 @@ import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.model.primitive.InstantDt; import ca.uhn.fhir.model.primitive.InstantDt;
import ca.uhn.fhir.model.valueset.BundleEntrySearchModeEnum; import ca.uhn.fhir.model.valueset.BundleEntrySearchModeEnum;
import ca.uhn.fhir.parser.DataFormatException; import ca.uhn.fhir.parser.DataFormatException;
import ca.uhn.fhir.rest.api.Constants; import ca.uhn.fhir.rest.api.*;
import ca.uhn.fhir.rest.api.QualifiedParamList;
import ca.uhn.fhir.rest.api.RestSearchParameterTypeEnum;
import ca.uhn.fhir.rest.api.SortOrderEnum;
import ca.uhn.fhir.rest.api.SortSpec;
import ca.uhn.fhir.rest.api.server.IPreResourceAccessDetails; import ca.uhn.fhir.rest.api.server.IPreResourceAccessDetails;
import ca.uhn.fhir.rest.api.server.RequestDetails; import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.param.*; import ca.uhn.fhir.rest.param.*;
@ -85,6 +63,7 @@ import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails; import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
import ca.uhn.fhir.util.StopWatch; import ca.uhn.fhir.util.StopWatch;
import ca.uhn.fhir.util.UrlUtil; import ca.uhn.fhir.util.UrlUtil;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
@ -119,11 +98,7 @@ import java.util.Map.Entry;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static org.apache.commons.lang3.ObjectUtils.defaultIfNull; import static org.apache.commons.lang3.ObjectUtils.defaultIfNull;
import static org.apache.commons.lang3.StringUtils.defaultIfBlank; import static org.apache.commons.lang3.StringUtils.*;
import static org.apache.commons.lang3.StringUtils.defaultString;
import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import static org.apache.commons.lang3.StringUtils.trim;
/** /**
* The SearchBuilder is responsible for actually forming the SQL query that handles * The SearchBuilder is responsible for actually forming the SQL query that handles
@ -2595,6 +2570,8 @@ public class SearchBuilder implements ISearchBuilder {
nextRoundMatches = pidsToInclude; nextRoundMatches = pidsToInclude;
} while (includes.size() > 0 && nextRoundMatches.size() > 0 && addedSomeThisRound); } while (includes.size() > 0 && nextRoundMatches.size() > 0 && addedSomeThisRound);
allAdded.removeAll(original);
ourLog.info("Loaded {} {} in {} rounds and {} ms for search {}", allAdded.size(), theReverseMode ? "_revincludes" : "_includes", roundCounts, w.getMillisAndRestart(), theSearchIdOrDescription); ourLog.info("Loaded {} {} in {} rounds and {} ms for search {}", allAdded.size(), theReverseMode ? "_revincludes" : "_includes", roundCounts, w.getMillisAndRestart(), theSearchIdOrDescription);
// Interceptor call: STORAGE_PREACCESS_RESOURCES // Interceptor call: STORAGE_PREACCESS_RESOURCES
@ -3109,19 +3086,26 @@ public class SearchBuilder implements ISearchBuilder {
} }
@VisibleForTesting
void setParamsForUnitTest(SearchParameterMap theParams) {
myParams = theParams;
}
SearchParameterMap getParams() {
return myParams;
}
public class IncludesIterator extends BaseIterator<ResourcePersistentId> implements Iterator<ResourcePersistentId> { public class IncludesIterator extends BaseIterator<ResourcePersistentId> implements Iterator<ResourcePersistentId> {
private final RequestDetails myRequest; private final RequestDetails myRequest;
private Iterator<ResourcePersistentId> myCurrentIterator; private Iterator<ResourcePersistentId> myCurrentIterator;
private int myCurrentOffset; private Set<ResourcePersistentId> myCurrentPids;
private ArrayList<ResourcePersistentId> myCurrentPids;
private ResourcePersistentId myNext; private ResourcePersistentId myNext;
private int myPageSize = myDaoConfig.getEverythingIncludesFetchPageSize(); private int myPageSize = myDaoConfig.getEverythingIncludesFetchPageSize();
IncludesIterator(Set<ResourcePersistentId> thePidSet, RequestDetails theRequest) { IncludesIterator(Set<ResourcePersistentId> thePidSet, RequestDetails theRequest) {
myCurrentPids = new ArrayList<>(thePidSet); myCurrentPids = new HashSet<>(thePidSet);
myCurrentIterator = EMPTY_LONG_LIST.iterator(); myCurrentIterator = EMPTY_LONG_LIST.iterator();
myCurrentOffset = 0;
myRequest = theRequest; myRequest = theRequest;
} }
@ -3133,21 +3117,13 @@ public class SearchBuilder implements ISearchBuilder {
break; break;
} }
int start = myCurrentOffset; Set<Include> includes = Collections.singleton(new Include("*", true));
int end = myCurrentOffset + myPageSize; Set<ResourcePersistentId> newPids = loadIncludes(myContext, myEntityManager, myCurrentPids, includes, false, getParams().getLastUpdated(), mySearchUuid, myRequest);
if (end > myCurrentPids.size()) { if (newPids.isEmpty()) {
end = myCurrentPids.size();
}
if (end - start <= 0) {
myNext = NO_MORE; myNext = NO_MORE;
break; break;
} }
myCurrentOffset = end;
Collection<ResourcePersistentId> pidsToScan = myCurrentPids.subList(start, end);
Set<Include> includes = Collections.singleton(new Include("*", true));
Set<ResourcePersistentId> newPids = loadIncludes(myContext, myEntityManager, pidsToScan, includes, false, myParams.getLastUpdated(), mySearchUuid, myRequest);
myCurrentIterator = newPids.iterator(); myCurrentIterator = newPids.iterator();
} }
} }
@ -3484,4 +3460,8 @@ public class SearchBuilder implements ISearchBuilder {
return thePredicates.toArray(new Predicate[0]); return thePredicates.toArray(new Predicate[0]);
} }
@VisibleForTesting
void setEntityManagerForUnitTest(EntityManager theEntityManager) {
myEntityManager = theEntityManager;
}
} }

View File

@ -1,25 +1,34 @@
package ca.uhn.fhir.jpa.dao; package ca.uhn.fhir.jpa.dao;
import ca.uhn.fhir.jpa.model.cross.ResourcePersistentId;
import ca.uhn.fhir.jpa.model.entity.ResourceLink;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.rest.param.ParamPrefixEnum;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;
import java.math.BigDecimal;
import java.math.MathContext;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import static org.hamcrest.Matchers.startsWith; import static org.hamcrest.Matchers.startsWith;
import static org.junit.Assert.*; import static org.junit.Assert.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.math.BigDecimal; @RunWith(MockitoJUnitRunner.class)
import java.math.MathContext;
import org.junit.AfterClass;
import org.junit.Test;
import ca.uhn.fhir.rest.param.ParamPrefixEnum;
import ca.uhn.fhir.util.TestUtil;
public class SearchBuilderTest { public class SearchBuilderTest {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(SearchBuilderTest.class); private static final Logger ourLog = LoggerFactory.getLogger(SearchBuilderTest.class);
@AfterClass
public static void afterClassClearContext() {
TestUtil.clearAllStaticFieldsForUnitTest();
}
@Test @Test
public void testCalculateMultiplierEqualNoDecimal() { public void testCalculateMultiplierEqualNoDecimal() {
@ -97,5 +106,32 @@ public class SearchBuilderTest {
assertThat(out.toPlainString(), startsWith("20.000")); assertThat(out.toPlainString(), startsWith("20.000"));
} }
@Test
public void testIncludeIterator() {
BaseHapiFhirDao<?> mockDao = mock(BaseHapiFhirDao.class);
when(mockDao.getConfig()).thenReturn(new DaoConfig());
SearchBuilder searchBuilder = new SearchBuilder(mockDao);
searchBuilder.setParamsForUnitTest(new SearchParameterMap());
EntityManager mockEntityManager = mock(EntityManager.class);
searchBuilder.setEntityManagerForUnitTest(mockEntityManager);
Set<ResourcePersistentId> pidSet = new HashSet<>();
pidSet.add(new ResourcePersistentId(1L));
pidSet.add(new ResourcePersistentId(2L));
TypedQuery mockQuery = mock(TypedQuery.class);
when(mockEntityManager.createQuery(any(), any())).thenReturn(mockQuery);
List<ResourceLink> resultList = new ArrayList<>();
ResourceLink link = new ResourceLink();
ResourceTable target = new ResourceTable();
target.setId(1L);
link.setTargetResource(target);
resultList.add(link);
when(mockQuery.getResultList()).thenReturn(resultList);
SearchBuilder.IncludesIterator includesIterator = searchBuilder.new IncludesIterator(pidSet, null);
// hasNext() should return false if the pid added was already on our list going in.
assertFalse(includesIterator.hasNext());
}
} }

View File

@ -1,11 +1,10 @@
package ca.uhn.fhir.jpa.provider.dstu3; package ca.uhn.fhir.jpa.provider.dstu3;
import static org.hamcrest.Matchers.*; import ca.uhn.fhir.jpa.dao.DaoConfig;
import static org.junit.Assert.*; import ca.uhn.fhir.parser.StrictErrorHandler;
import ca.uhn.fhir.rest.api.EncodingEnum;
import java.io.IOException; import ca.uhn.fhir.util.TestUtil;
import java.util.*; import com.google.common.base.Charsets;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.apache.http.client.ClientProtocolException; import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.CloseableHttpResponse;
@ -14,25 +13,31 @@ import org.hl7.fhir.dstu3.model.*;
import org.hl7.fhir.dstu3.model.Bundle.BundleEntryComponent; import org.hl7.fhir.dstu3.model.Bundle.BundleEntryComponent;
import org.hl7.fhir.dstu3.model.Encounter.EncounterStatus; import org.hl7.fhir.dstu3.model.Encounter.EncounterStatus;
import org.hl7.fhir.dstu3.model.Observation.ObservationStatus; import org.hl7.fhir.dstu3.model.Observation.ObservationStatus;
import org.junit.*; import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.Test;
import com.google.common.base.Charsets; import java.io.IOException;
import java.util.ArrayList;
import java.util.Set;
import java.util.TreeSet;
import ca.uhn.fhir.jpa.dao.DaoConfig; import static org.hamcrest.Matchers.*;
import ca.uhn.fhir.parser.StrictErrorHandler; import static org.junit.Assert.*;
import ca.uhn.fhir.rest.api.EncodingEnum;
import ca.uhn.fhir.util.TestUtil;
public class PatientEverythingDstu3Test extends BaseResourceProviderDstu3Test { public class PatientEverythingDstu3Test extends BaseResourceProviderDstu3Test {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(PatientEverythingDstu3Test.class); private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(PatientEverythingDstu3Test.class);
private String orgId; private String myOrgId;
private String patId; private String myPatientId;
private String encId1; private String encId1;
private String encId2; private String encId2;
private ArrayList<String> myObsIds; private ArrayList<String> myObsIds;
private String myWrongPatId; private String myWrongPatId;
private String myWrongEnc1; private String myWrongEnc1;
private Organization myOrg;
private Patient myPatient;
@Before @Before
public void beforeDisableResultReuse() { public void beforeDisableResultReuse() {
@ -55,41 +60,43 @@ public class PatientEverythingDstu3Test extends BaseResourceProviderDstu3Test {
myDaoConfig.setAllowMultipleDelete(true); myDaoConfig.setAllowMultipleDelete(true);
Organization org = new Organization(); myOrg = new Organization();
org.setName("an org"); myOrg.setName("an org");
orgId = ourClient.create().resource(org).execute().getId().toUnqualifiedVersionless().getValue(); myOrgId = ourClient.create().resource(myOrg).execute().getId().toUnqualifiedVersionless().getValue();
ourLog.info("OrgId: {}", orgId); myOrg.setId(myOrgId);
ourLog.info("OrgId: {}", myOrgId);
Patient patient = new Patient(); myPatient = new Patient();
patient.getManagingOrganization().setReference(orgId); myPatient.getManagingOrganization().setReference(myOrgId);
patId = ourClient.create().resource(patient).execute().getId().toUnqualifiedVersionless().getValue(); myPatientId = ourClient.create().resource(myPatient).execute().getId().toUnqualifiedVersionless().getValue();
myPatient.setId(myPatientId);
Patient patient2 = new Patient(); Patient patient2 = new Patient();
patient2.getManagingOrganization().setReference(orgId); patient2.getManagingOrganization().setReference(myOrgId);
myWrongPatId = ourClient.create().resource(patient2).execute().getId().toUnqualifiedVersionless().getValue(); myWrongPatId = ourClient.create().resource(patient2).execute().getId().toUnqualifiedVersionless().getValue();
Encounter enc1 = new Encounter(); Encounter enc1 = new Encounter();
enc1.setStatus(EncounterStatus.CANCELLED); enc1.setStatus(EncounterStatus.CANCELLED);
enc1.getSubject().setReference(patId); enc1.getSubject().setReference(myPatientId);
enc1.getServiceProvider().setReference(orgId); enc1.getServiceProvider().setReference(myOrgId);
encId1 = ourClient.create().resource(enc1).execute().getId().toUnqualifiedVersionless().getValue(); encId1 = ourClient.create().resource(enc1).execute().getId().toUnqualifiedVersionless().getValue();
Encounter enc2 = new Encounter(); Encounter enc2 = new Encounter();
enc2.setStatus(EncounterStatus.ARRIVED); enc2.setStatus(EncounterStatus.ARRIVED);
enc2.getSubject().setReference(patId); enc2.getSubject().setReference(myPatientId);
enc2.getServiceProvider().setReference(orgId); enc2.getServiceProvider().setReference(myOrgId);
encId2 = ourClient.create().resource(enc2).execute().getId().toUnqualifiedVersionless().getValue(); encId2 = ourClient.create().resource(enc2).execute().getId().toUnqualifiedVersionless().getValue();
Encounter wrongEnc1 = new Encounter(); Encounter wrongEnc1 = new Encounter();
wrongEnc1.setStatus(EncounterStatus.ARRIVED); wrongEnc1.setStatus(EncounterStatus.ARRIVED);
wrongEnc1.getSubject().setReference(myWrongPatId); wrongEnc1.getSubject().setReference(myWrongPatId);
wrongEnc1.getServiceProvider().setReference(orgId); wrongEnc1.getServiceProvider().setReference(myOrgId);
myWrongEnc1 = ourClient.create().resource(wrongEnc1).execute().getId().toUnqualifiedVersionless().getValue(); myWrongEnc1 = ourClient.create().resource(wrongEnc1).execute().getId().toUnqualifiedVersionless().getValue();
myObsIds = new ArrayList<String>(); myObsIds = new ArrayList<String>();
for (int i = 0; i < 20; i++) { for (int i = 0; i < 20; i++) {
Observation obs = new Observation(); Observation obs = new Observation();
obs.getSubject().setReference(patId); obs.getSubject().setReference(myPatientId);
obs.setStatus(ObservationStatus.FINAL); obs.setStatus(ObservationStatus.FINAL);
String obsId = ourClient.create().resource(obs).execute().getId().toUnqualifiedVersionless().getValue(); String obsId = ourClient.create().resource(obs).execute().getId().toUnqualifiedVersionless().getValue();
myObsIds.add(obsId); myObsIds.add(obsId);
@ -103,7 +110,7 @@ public class PatientEverythingDstu3Test extends BaseResourceProviderDstu3Test {
@Test @Test
public void testEverythingReturnsCorrectResources() throws Exception { public void testEverythingReturnsCorrectResources() throws Exception {
Bundle bundle = fetchBundle(ourServerBase + "/" + patId + "/$everything?_format=json&_count=100", EncodingEnum.JSON); Bundle bundle = fetchBundle(ourServerBase + "/" + myPatientId + "/$everything?_format=json&_count=100", EncodingEnum.JSON);
assertNull(bundle.getLink("next")); assertNull(bundle.getLink("next"));
@ -114,15 +121,51 @@ public class PatientEverythingDstu3Test extends BaseResourceProviderDstu3Test {
ourLog.info("Found IDs: {}", actual); ourLog.info("Found IDs: {}", actual);
assertThat(actual, hasItem(patId)); assertThat(actual, hasItem(myPatientId));
assertThat(actual, hasItem(encId1)); assertThat(actual, hasItem(encId1));
assertThat(actual, hasItem(encId2)); assertThat(actual, hasItem(encId2));
assertThat(actual, hasItem(orgId)); assertThat(actual, hasItem(myOrgId));
assertThat(actual, hasItems(myObsIds.toArray(new String[0]))); assertThat(actual, hasItems(myObsIds.toArray(new String[0])));
assertThat(actual, not(hasItem(myWrongPatId))); assertThat(actual, not(hasItem(myWrongPatId)));
assertThat(actual, not(hasItem(myWrongEnc1))); assertThat(actual, not(hasItem(myWrongEnc1)));
} }
@Test
public void testEverythingHandlesCircularReferences() throws Exception {
Patient linkedPatient1 = new Patient();
linkedPatient1.addLink().setOther(new Reference(myPatientId));
String linkedPatient1Id = ourClient.create().resource(linkedPatient1).execute().getId().toUnqualifiedVersionless().getValue();
Patient linkedPatient2 = new Patient();
linkedPatient2.addLink().setOther(new Reference(linkedPatient1Id));
String linkedPatient2Id = ourClient.create().resource(linkedPatient2).execute().getId().toUnqualifiedVersionless().getValue();
myPatient.addLink().setOther(new Reference(linkedPatient2Id));
ourClient.update().resource(myPatient).execute();
Bundle bundle = fetchBundle(ourServerBase + "/" + myPatientId + "/$everything?_format=json&_count=100", EncodingEnum.JSON);
assertNull(bundle.getLink("next"));
Set<String> actual = new TreeSet<String>();
for (BundleEntryComponent nextEntry : bundle.getEntry()) {
actual.add(nextEntry.getResource().getIdElement().toUnqualifiedVersionless().getValue());
}
ourLog.info("Found IDs: {}", actual);
assertThat(actual, hasItem(myPatientId));
assertThat(actual, hasItem(linkedPatient1Id));
assertThat(actual, hasItem(linkedPatient2Id));
assertThat(actual, hasItem(encId1));
assertThat(actual, hasItem(encId2));
assertThat(actual, hasItem(myOrgId));
assertThat(actual, hasItems(myObsIds.toArray(new String[0])));
assertThat(actual, not(hasItem(myWrongPatId)));
assertThat(actual, not(hasItem(myWrongEnc1)));
}
/** /**
* See #674 * See #674
*/ */
@ -130,7 +173,7 @@ public class PatientEverythingDstu3Test extends BaseResourceProviderDstu3Test {
public void testEverythingReturnsCorrectResourcesSmallPage() throws Exception { public void testEverythingReturnsCorrectResourcesSmallPage() throws Exception {
myDaoConfig.setEverythingIncludesFetchPageSize(1); myDaoConfig.setEverythingIncludesFetchPageSize(1);
Bundle bundle = fetchBundle(ourServerBase + "/" + patId + "/$everything?_format=json&_count=100", EncodingEnum.JSON); Bundle bundle = fetchBundle(ourServerBase + "/" + myPatientId + "/$everything?_format=json&_count=100", EncodingEnum.JSON);
assertNull(bundle.getLink("next")); assertNull(bundle.getLink("next"));
@ -141,10 +184,10 @@ public class PatientEverythingDstu3Test extends BaseResourceProviderDstu3Test {
ourLog.info("Found IDs: {}", actual); ourLog.info("Found IDs: {}", actual);
assertThat(actual, hasItem(patId)); assertThat(actual, hasItem(myPatientId));
assertThat(actual, hasItem(encId1)); assertThat(actual, hasItem(encId1));
assertThat(actual, hasItem(encId2)); assertThat(actual, hasItem(encId2));
assertThat(actual, hasItem(orgId)); assertThat(actual, hasItem(myOrgId));
assertThat(actual, hasItems(myObsIds.toArray(new String[0]))); assertThat(actual, hasItems(myObsIds.toArray(new String[0])));
assertThat(actual, not(hasItem(myWrongPatId))); assertThat(actual, not(hasItem(myWrongPatId)));
assertThat(actual, not(hasItem(myWrongEnc1))); assertThat(actual, not(hasItem(myWrongEnc1)));
@ -156,7 +199,7 @@ public class PatientEverythingDstu3Test extends BaseResourceProviderDstu3Test {
@Test @Test
public void testEverythingPagesWithCorrectEncodingJson() throws Exception { public void testEverythingPagesWithCorrectEncodingJson() throws Exception {
Bundle bundle = fetchBundle(ourServerBase + "/" + patId + "/$everything?_format=json&_count=1", EncodingEnum.JSON); Bundle bundle = fetchBundle(ourServerBase + "/" + myPatientId + "/$everything?_format=json&_count=1", EncodingEnum.JSON);
assertNotNull(bundle.getLink("next").getUrl()); assertNotNull(bundle.getLink("next").getUrl());
assertThat(bundle.getLink("next").getUrl(), containsString("_format=json")); assertThat(bundle.getLink("next").getUrl(), containsString("_format=json"));
@ -173,7 +216,7 @@ public class PatientEverythingDstu3Test extends BaseResourceProviderDstu3Test {
@Test @Test
public void testEverythingPagesWithCorrectEncodingXml() throws Exception { public void testEverythingPagesWithCorrectEncodingXml() throws Exception {
Bundle bundle = fetchBundle(ourServerBase + "/" + patId + "/$everything?_format=xml&_count=1", EncodingEnum.XML); Bundle bundle = fetchBundle(ourServerBase + "/" + myPatientId + "/$everything?_format=xml&_count=1", EncodingEnum.XML);
assertNotNull(bundle.getLink("next").getUrl()); assertNotNull(bundle.getLink("next").getUrl());
ourLog.info("Next link: {}", bundle.getLink("next").getUrl()); ourLog.info("Next link: {}", bundle.getLink("next").getUrl());