Add a test
This commit is contained in:
parent
ce720f5601
commit
ff85503acb
|
@ -89,7 +89,7 @@ public class SearchParamPresenceSvcImpl implements ISearchParamPresenceSvc {
|
|||
searchParam = new SearchParam();
|
||||
searchParam.setResourceName(resourceType);
|
||||
searchParam.setParamName(paramName);
|
||||
searchParam = mySearchParamDao.saveAndFlush(searchParam);
|
||||
searchParam = mySearchParamDao.save(searchParam);
|
||||
ourLog.info("Added search param {} with pid {}", paramName, searchParam.getId());
|
||||
// Don't add the newly saved entity to the map in case the save fails
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import ca.uhn.fhir.jpa.entity.ResourceTable;
|
|||
import ca.uhn.fhir.jpa.entity.ResourceTag;
|
||||
import ca.uhn.fhir.jpa.entity.TagTypeEnum;
|
||||
import ca.uhn.fhir.jpa.provider.SystemProviderDstu2Test;
|
||||
import ca.uhn.fhir.jpa.util.StopWatch;
|
||||
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.rest.api.Constants;
|
||||
|
@ -37,9 +38,12 @@ import java.io.InputStream;
|
|||
import java.io.UnsupportedEncodingException;
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
@ -62,43 +66,6 @@ public class FhirSystemDaoDstu3Test extends BaseJpaDstu3SystemTest {
|
|||
myDaoConfig.setReuseCachedSearchResultsForMillis(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionWhichFailsPersistsNothing() {
|
||||
|
||||
// Run a transaction which points to that practitioner
|
||||
// in a field that isn't allowed to refer to a practitioner
|
||||
Bundle input = new Bundle();
|
||||
input.setType(BundleType.TRANSACTION);
|
||||
|
||||
Patient pt = new Patient();
|
||||
pt.setId("PT");
|
||||
pt.setActive(true);
|
||||
pt.addName().setFamily("FAMILY");
|
||||
input.addEntry()
|
||||
.setResource(pt)
|
||||
.getRequest().setMethod(HTTPVerb.PUT).setUrl("Patient/PT");
|
||||
|
||||
Observation obs = new Observation();
|
||||
obs.setId("OBS");
|
||||
obs.getCode().addCoding().setSystem("foo").setCode("bar");
|
||||
obs.addPerformer().setReference("Practicioner/AAAAA");
|
||||
input.addEntry()
|
||||
.setResource(obs)
|
||||
.getRequest().setMethod(HTTPVerb.PUT).setUrl("Observation/OBS");
|
||||
|
||||
try {
|
||||
mySystemDao.transaction(mySrd, input);
|
||||
fail();
|
||||
} catch (UnprocessableEntityException e) {
|
||||
assertThat(e.getMessage(), containsString("Resource type 'Practicioner' is not valid for this path"));
|
||||
}
|
||||
|
||||
assertThat(myResourceTableDao.findAll(), empty());
|
||||
assertThat(myResourceIndexedSearchParamStringDao.findAll(), empty());
|
||||
|
||||
}
|
||||
|
||||
|
||||
private Bundle createInputTransactionWithPlaceholderIdInMatchUrl(HTTPVerb theVerb) {
|
||||
|
||||
Patient pat = new Patient();
|
||||
|
@ -209,6 +176,11 @@ public class FhirSystemDaoDstu3Test extends BaseJpaDstu3SystemTest {
|
|||
return null;
|
||||
}
|
||||
|
||||
private Bundle loadBundle(String theFileName) throws IOException {
|
||||
String req = IOUtils.toString(FhirSystemDaoDstu3Test.class.getResourceAsStream(theFileName), StandardCharsets.UTF_8);
|
||||
return myFhirCtx.newXmlParser().parseResource(Bundle.class, req);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBatchCreateWithBadRead() {
|
||||
Bundle request = new Bundle();
|
||||
|
@ -1222,8 +1194,7 @@ public class FhirSystemDaoDstu3Test extends BaseJpaDstu3SystemTest {
|
|||
|
||||
@Test
|
||||
public void testTransactionCreateWithPutUsingUrl2() throws Exception {
|
||||
String req = IOUtils.toString(FhirSystemDaoDstu3Test.class.getResourceAsStream("/bundle-dstu3.xml"), StandardCharsets.UTF_8);
|
||||
Bundle request = myFhirCtx.newXmlParser().parseResource(Bundle.class, req);
|
||||
Bundle request = loadBundle("/bundle-dstu3.xml");
|
||||
mySystemDao.transaction(mySrd, request);
|
||||
}
|
||||
|
||||
|
@ -1702,13 +1673,13 @@ public class FhirSystemDaoDstu3Test extends BaseJpaDstu3SystemTest {
|
|||
//@formatter:off
|
||||
/*
|
||||
* Transaction Order, per the spec:
|
||||
*
|
||||
*
|
||||
* Process any DELETE interactions
|
||||
* Process any POST interactions
|
||||
* Process any PUT interactions
|
||||
* Process any GET interactions
|
||||
*
|
||||
* This test creates a transaction bundle that includes
|
||||
*
|
||||
* This test creates a transaction bundle that includes
|
||||
* these four operations in the reverse order and verifies
|
||||
* that they are invoked correctly.
|
||||
*/
|
||||
|
@ -2147,6 +2118,42 @@ public class FhirSystemDaoDstu3Test extends BaseJpaDstu3SystemTest {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionWhichFailsPersistsNothing() {
|
||||
|
||||
// Run a transaction which points to that practitioner
|
||||
// in a field that isn't allowed to refer to a practitioner
|
||||
Bundle input = new Bundle();
|
||||
input.setType(BundleType.TRANSACTION);
|
||||
|
||||
Patient pt = new Patient();
|
||||
pt.setId("PT");
|
||||
pt.setActive(true);
|
||||
pt.addName().setFamily("FAMILY");
|
||||
input.addEntry()
|
||||
.setResource(pt)
|
||||
.getRequest().setMethod(HTTPVerb.PUT).setUrl("Patient/PT");
|
||||
|
||||
Observation obs = new Observation();
|
||||
obs.setId("OBS");
|
||||
obs.getCode().addCoding().setSystem("foo").setCode("bar");
|
||||
obs.addPerformer().setReference("Practicioner/AAAAA");
|
||||
input.addEntry()
|
||||
.setResource(obs)
|
||||
.getRequest().setMethod(HTTPVerb.PUT).setUrl("Observation/OBS");
|
||||
|
||||
try {
|
||||
mySystemDao.transaction(mySrd, input);
|
||||
fail();
|
||||
} catch (UnprocessableEntityException e) {
|
||||
assertThat(e.getMessage(), containsString("Resource type 'Practicioner' is not valid for this path"));
|
||||
}
|
||||
|
||||
assertThat(myResourceTableDao.findAll(), empty());
|
||||
assertThat(myResourceIndexedSearchParamStringDao.findAll(), empty());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Format changed, source isn't valid
|
||||
*/
|
||||
|
@ -2815,6 +2822,92 @@ public class FhirSystemDaoDstu3Test extends BaseJpaDstu3SystemTest {
|
|||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testMultipleConcurrentWritesToSameResource() throws InterruptedException {
|
||||
|
||||
ThreadPoolExecutor exec = new ThreadPoolExecutor(10, 10,
|
||||
0L, TimeUnit.MILLISECONDS,
|
||||
new LinkedBlockingQueue<Runnable>());
|
||||
|
||||
final AtomicInteger errors = new AtomicInteger();
|
||||
|
||||
List<Future> futures = new ArrayList<>();
|
||||
for (int i = 0; i < 50; i++) {
|
||||
final Patient p = new Patient();
|
||||
p.setId("PID");
|
||||
p.setActive(true);
|
||||
p.setBirthDate(new Date());
|
||||
p.addIdentifier().setSystem("foo1");
|
||||
p.addIdentifier().setSystem("foo2");
|
||||
p.addIdentifier().setSystem("foo3");
|
||||
p.addIdentifier().setSystem("foo4");
|
||||
p.addName().setFamily("FOO" + i);
|
||||
p.addName().addGiven("AAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBB1");
|
||||
p.addName().addGiven("AAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBB2");
|
||||
p.addName().addGiven("AAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBB3");
|
||||
p.addName().addGiven("AAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBB4");
|
||||
p.addName().addGiven("AAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBB5");
|
||||
p.addName().addGiven("AAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBB6");
|
||||
|
||||
Organization o = new Organization();
|
||||
o.setName("ORG" + i);
|
||||
|
||||
final Bundle t = new Bundle();
|
||||
t.setType(BundleType.TRANSACTION);
|
||||
t.addEntry()
|
||||
.setResource(p)
|
||||
.getRequest()
|
||||
.setUrl("Patient/PID")
|
||||
.setMethod(HTTPVerb.PUT);
|
||||
t.addEntry()
|
||||
.setResource(o)
|
||||
.getRequest()
|
||||
.setUrl("Organization")
|
||||
.setMethod(HTTPVerb.POST);
|
||||
|
||||
if (i == 0) {
|
||||
mySystemDao.transaction(mySrd, t);
|
||||
}
|
||||
futures.add(exec.submit(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
mySystemDao.transaction(mySrd, t);
|
||||
} catch (Exception e) {
|
||||
ourLog.error("Failed to update", e);
|
||||
errors.incrementAndGet();
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
ourLog.info("Shutting down excutor");
|
||||
StopWatch sw = new StopWatch();
|
||||
for (Future next : futures) {
|
||||
while (!next.isDone()) {
|
||||
Thread.sleep(20);
|
||||
}
|
||||
}
|
||||
exec.shutdown();
|
||||
ourLog.info("Shut down excutor in {}ms", sw.getMillis());
|
||||
ourLog.info("Had {} errors", errors.get());
|
||||
|
||||
Patient currentPatient = myPatientDao.read(new IdType("Patient/PID"));
|
||||
Long currentVersion = currentPatient.getIdElement().getVersionIdPartAsLong();
|
||||
ourLog.info("Current version: {}", currentVersion);
|
||||
|
||||
IBundleProvider historyBundle = myPatientDao.history(new IdType("Patient/PID"),null,null,mySrd);
|
||||
Patient lastPatient = (Patient) historyBundle.getResources(0,1).get(0);
|
||||
Long lastVersion = lastPatient.getIdElement().getVersionIdPartAsLong();
|
||||
ourLog.info("Last version: {}", lastVersion);
|
||||
|
||||
assertEquals(currentVersion, lastVersion);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@AfterClass
|
||||
public static void afterClassClearContext() {
|
||||
TestUtil.clearAllStaticFieldsForUnitTest();
|
||||
|
|
|
@ -1,51 +1,54 @@
|
|||
package ca.uhn.fhir.jpa.stresstest;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import ca.uhn.fhir.jpa.provider.dstu3.BaseResourceProviderDstu3Test;
|
||||
import ca.uhn.fhir.rest.api.Constants;
|
||||
import ca.uhn.fhir.rest.server.interceptor.RequestValidatingInterceptor;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
import com.google.common.base.Charsets;
|
||||
import com.google.common.collect.Lists;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.hl7.fhir.dstu3.hapi.validation.FhirInstanceValidator;
|
||||
import org.hl7.fhir.dstu3.model.*;
|
||||
import org.hl7.fhir.dstu3.model.Bundle;
|
||||
import org.hl7.fhir.dstu3.model.Bundle.BundleType;
|
||||
import org.hl7.fhir.dstu3.model.Bundle.HTTPVerb;
|
||||
import org.junit.*;
|
||||
import org.hl7.fhir.dstu3.model.CodeableConcept;
|
||||
import org.hl7.fhir.dstu3.model.Coding;
|
||||
import org.hl7.fhir.dstu3.model.Patient;
|
||||
import org.junit.After;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.google.common.base.Charsets;
|
||||
import com.google.common.collect.Lists;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import ca.uhn.fhir.jpa.provider.dstu3.BaseResourceProviderDstu3Test;
|
||||
import ca.uhn.fhir.rest.server.interceptor.RequestValidatingInterceptor;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class StressTestDstu3Test extends BaseResourceProviderDstu3Test {
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(StressTestDstu3Test.class);
|
||||
private RequestValidatingInterceptor myRequestValidatingInterceptor;
|
||||
|
||||
@After
|
||||
public void after() throws Exception {
|
||||
super.after();
|
||||
|
||||
ourRestServer.unregisterInterceptor(myRequestValidatingInterceptor);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void before() throws Exception {
|
||||
super.before();
|
||||
|
||||
|
||||
myRequestValidatingInterceptor = new RequestValidatingInterceptor();
|
||||
FhirInstanceValidator module = new FhirInstanceValidator();
|
||||
module.setValidationSupport(myValidationSupport);
|
||||
myRequestValidatingInterceptor.addValidatorModule(module);
|
||||
}
|
||||
|
||||
@After
|
||||
public void after() throws Exception {
|
||||
super.after();
|
||||
|
||||
ourRestServer.unregisterInterceptor(myRequestValidatingInterceptor);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testMultithreadedSearch() throws Exception {
|
||||
Bundle input = new Bundle();
|
||||
|
@ -56,8 +59,8 @@ public class StressTestDstu3Test extends BaseResourceProviderDstu3Test {
|
|||
input.addEntry().setResource(p).getRequest().setMethod(HTTPVerb.POST).setUrl("Patient");
|
||||
}
|
||||
ourClient.transaction().withBundle(input).execute();
|
||||
|
||||
|
||||
|
||||
|
||||
List<BaseTask> tasks = Lists.newArrayList();
|
||||
try {
|
||||
for (int threadIndex = 0; threadIndex < 10; threadIndex++) {
|
||||
|
@ -74,10 +77,9 @@ public class StressTestDstu3Test extends BaseResourceProviderDstu3Test {
|
|||
validateNoErrors(tasks);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* This test prevents a deadlock that was detected with a large number of
|
||||
* This test prevents a deadlock that was detected with a large number of
|
||||
* threads creating resources and blocking on the searchparamcache refreshing
|
||||
* (since this is a synchronized method) while the instance that was actually
|
||||
* executing was waiting on a DB connection. This was solved by making
|
||||
|
@ -87,7 +89,7 @@ public class StressTestDstu3Test extends BaseResourceProviderDstu3Test {
|
|||
@Test
|
||||
public void testMultithreadedSearchWithValidation() throws Exception {
|
||||
ourRestServer.registerInterceptor(myRequestValidatingInterceptor);
|
||||
|
||||
|
||||
Bundle input = new Bundle();
|
||||
input.setType(BundleType.TRANSACTION);
|
||||
for (int i = 0; i < 500; i++) {
|
||||
|
@ -96,7 +98,7 @@ public class StressTestDstu3Test extends BaseResourceProviderDstu3Test {
|
|||
input.addEntry().setResource(p).getRequest().setMethod(HTTPVerb.POST).setUrl("Patient");
|
||||
}
|
||||
ourClient.transaction().withBundle(input).execute();
|
||||
|
||||
|
||||
CloseableHttpResponse getMeta = ourHttpClient.execute(new HttpGet(ourServerBase + "/metadata"));
|
||||
try {
|
||||
assertEquals(200, getMeta.getStatusLine().getStatusCode());
|
||||
|
@ -133,7 +135,7 @@ public class StressTestDstu3Test extends BaseResourceProviderDstu3Test {
|
|||
}
|
||||
total += next.getTaskCount();
|
||||
}
|
||||
|
||||
|
||||
ourLog.info("Loaded {} searches", total);
|
||||
}
|
||||
|
||||
|
@ -142,14 +144,14 @@ public class StressTestDstu3Test extends BaseResourceProviderDstu3Test {
|
|||
TestUtil.clearAllStaticFieldsForUnitTest();
|
||||
}
|
||||
|
||||
public class BaseTask extends Thread {
|
||||
public class BaseTask extends Thread {
|
||||
protected Throwable myError;
|
||||
protected int myTaskCount = 0;
|
||||
|
||||
|
||||
public BaseTask() {
|
||||
setDaemon(true);
|
||||
}
|
||||
|
||||
|
||||
public Throwable getError() {
|
||||
return myError;
|
||||
}
|
||||
|
@ -168,7 +170,7 @@ public class StressTestDstu3Test extends BaseResourceProviderDstu3Test {
|
|||
for (int i = 0; i < 10; i++) {
|
||||
try {
|
||||
Bundle respBundle;
|
||||
|
||||
|
||||
// Load search
|
||||
HttpGet get = new HttpGet(ourServerBase + "/Patient?identifier=http%3A%2F%2Ftest%7CBAR," + UUID.randomUUID().toString());
|
||||
get.addHeader(Constants.HEADER_CONTENT_TYPE, Constants.CT_FHIR_JSON_NEW);
|
||||
|
@ -181,7 +183,7 @@ public class StressTestDstu3Test extends BaseResourceProviderDstu3Test {
|
|||
} finally {
|
||||
IOUtils.closeQuietly(getResp);
|
||||
}
|
||||
|
||||
|
||||
// Load page 2
|
||||
get = new HttpGet(respBundle.getLink("next").getUrl());
|
||||
get.addHeader(Constants.HEADER_CONTENT_TYPE, Constants.CT_FHIR_JSON_NEW);
|
||||
|
@ -194,7 +196,7 @@ public class StressTestDstu3Test extends BaseResourceProviderDstu3Test {
|
|||
} finally {
|
||||
IOUtils.closeQuietly(getResp);
|
||||
}
|
||||
|
||||
|
||||
} catch (Throwable e) {
|
||||
ourLog.error("Failure during search", e);
|
||||
myError = e;
|
||||
|
@ -214,9 +216,9 @@ public class StressTestDstu3Test extends BaseResourceProviderDstu3Test {
|
|||
p.addIdentifier().setSystem("http://test").setValue("BAR").setType(new CodeableConcept().addCoding(new Coding().setSystem("http://foo").setCode("bar")));
|
||||
p.setGender(org.hl7.fhir.dstu3.model.Enumerations.AdministrativeGender.MALE);
|
||||
ourClient.create().resource(p).execute();
|
||||
|
||||
|
||||
ourSearchParamRegistry.forceRefresh();
|
||||
|
||||
|
||||
} catch (Throwable e) {
|
||||
ourLog.error("Failure during search", e);
|
||||
myError = e;
|
||||
|
@ -226,4 +228,5 @@ public class StressTestDstu3Test extends BaseResourceProviderDstu3Test {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue