diff --git a/adapter/adapter-service/src/test/scala/net/shrine/adapter/AbstractQueryRetrievalTestCase.scala b/adapter/adapter-service/src/test/scala/net/shrine/adapter/AbstractQueryRetrievalTestCase.scala index e644441a4..2ba6d8a17 100644 --- a/adapter/adapter-service/src/test/scala/net/shrine/adapter/AbstractQueryRetrievalTestCase.scala +++ b/adapter/adapter-service/src/test/scala/net/shrine/adapter/AbstractQueryRetrievalTestCase.scala @@ -1,375 +1,377 @@ package net.shrine.adapter +import net.shrine.problem.{TestProblem, ProblemSources, AbstractProblem} + import scala.xml.NodeSeq import net.shrine.util.ShouldMatchersForJUnit import ObfuscatorTest.within3 import javax.xml.datatype.XMLGregorianCalendar import net.shrine.adapter.dao.AdapterDao import net.shrine.adapter.dao.squeryl.AbstractSquerylAdapterTest import net.shrine.client.HttpClient import net.shrine.client.HttpResponse import net.shrine.protocol.{HiveCredentials, AuthenticationInfo, BroadcastMessage, CrcRequest, Credential, ErrorResponse, I2b2ResultEnvelope, QueryResult, ReadResultRequest, ReadResultResponse, ResultOutputType, ShrineRequest, ShrineResponse, BaseShrineResponse, BaseShrineRequest, RunQueryRequest, RunQueryResponse, DefaultBreakdownResultOutputTypes} import net.shrine.protocol.DefaultBreakdownResultOutputTypes.PATIENT_AGE_COUNT_XML import net.shrine.protocol.ResultOutputType.PATIENT_COUNT_XML import net.shrine.protocol.DefaultBreakdownResultOutputTypes.PATIENT_GENDER_COUNT_XML import net.shrine.protocol.query.{QueryDefinition, Term} import net.shrine.util.XmlDateHelper import net.shrine.util.XmlDateHelper.now import net.shrine.util.XmlGcEnrichments import net.shrine.client.Poster import net.shrine.adapter.translators.QueryDefinitionTranslator import net.shrine.adapter.translators.ExpressionTranslator import scala.util.Success /** * @author clint * @since Nov 8, 2012 */ //noinspection UnitMethodIsParameterless abstract class AbstractQueryRetrievalTestCase[R <: BaseShrineResponse]( makeAdapter: (AdapterDao, HttpClient) => WithHiveCredentialsAdapter, makeRequest: (Long, AuthenticationInfo) => BaseShrineRequest, extractor: R => Option[(Long, QueryResult)]) extends AbstractSquerylAdapterTest with ShouldMatchersForJUnit { private val authn = AuthenticationInfo("some-domain", "some-user", Credential("alskdjlkasd", false)) def doTestProcessRequestMissingQuery { val adapter = makeAdapter(dao, MockHttpClient) val response = adapter.processRequest(BroadcastMessage(0L, authn, makeRequest(-1L, authn))) response.isInstanceOf[ErrorResponse] should be(true) } def doTestProcessInvalidRequest { val adapter = makeAdapter(dao, MockHttpClient) intercept[ClassCastException] { //request must be a type of request we can handle adapter.processRequest(BroadcastMessage(0L, authn, new AbstractQueryRetrievalTestCase.BogusRequest)) } } private val localMasterId = "alksjdkalsdjlasdjlkjsad" private val shrineNetworkQueryId = 123L private def doGetResults(adapter: Adapter) = adapter.processRequest(BroadcastMessage(shrineNetworkQueryId, authn, makeRequest(shrineNetworkQueryId, authn))) private def toMillis(xmlGc: XMLGregorianCalendar): Long = xmlGc.toGregorianCalendar.getTimeInMillis private val instanceId = 999L private val setSize = 12345L private val obfSetSize = setSize + 1 private val queryExpr = Term("foo") private val topicId = "laskdjlkasd" private val fooQuery = QueryDefinition("some-query",queryExpr) def doTestProcessRequestIncompleteQuery(countQueryShouldWork: Boolean = true): Unit = afterCreatingTables { val dbQueryId = dao.insertQuery(localMasterId, shrineNetworkQueryId, authn, fooQuery, isFlagged = false, hasBeenRun = true, flagMessage = None) import ResultOutputType._ import XmlDateHelper.now val breakdowns = Map(PATIENT_AGE_COUNT_XML -> I2b2ResultEnvelope(PATIENT_AGE_COUNT_XML, Map("a" -> 1L, "b" -> 2L))) val obfscBreakdowns = breakdowns.mapValues(_.mapValues(_ + 1)) val startDate = now val elapsed = 100L val endDate = { import XmlGcEnrichments._ import scala.concurrent.duration._ startDate + elapsed.milliseconds } val countResultId = 456L val breakdownResultId = 98237943265436L val incompleteCountResult = QueryResult( resultId = countResultId, instanceId = instanceId, resultType = Some(PATIENT_COUNT_XML), setSize = setSize, startDate = Option(startDate), endDate = Option(endDate), description = Some("results from node X"), statusType = QueryResult.StatusType.Processing, statusMessage = None, breakdowns = breakdowns) val breakdownResult = breakdowns.head match { case (resultType, data) => incompleteCountResult.withId(breakdownResultId).withBreakdowns(Map(resultType -> data)).withResultType(resultType) } val queryStartDate = now val idsByResultType = dao.insertQueryResults(dbQueryId, incompleteCountResult :: breakdownResult :: Nil) final class MightWorkMockHttpClient(expectedHiveCredentials: HiveCredentials) extends HttpClient { override def post(input: String, url: String): HttpResponse = { def makeFinished(queryResult: QueryResult) = queryResult.copy(statusType = QueryResult.StatusType.Finished) def validateAuthnAndProjectId(req: ShrineRequest) { req.authn should equal(expectedHiveCredentials.toAuthenticationInfo) req.projectId should equal(expectedHiveCredentials.projectId) } val response = CrcRequest.fromI2b2String(DefaultBreakdownResultOutputTypes.toSet)(input) match { case Success(req: ReadResultRequest) if req.localResultId == countResultId.toString => { validateAuthnAndProjectId(req) if (countQueryShouldWork) { ReadResultResponse(123L, makeFinished(incompleteCountResult), I2b2ResultEnvelope(PATIENT_COUNT_XML, Map(PATIENT_COUNT_XML.name -> incompleteCountResult.setSize))) } else { - ErrorResponse("Retrieving count result failed") + ErrorResponse(TestProblem(summary = "Retrieving count result failed")) } } case Success(req: ReadResultRequest) if req.localResultId == breakdownResultId.toString => { validateAuthnAndProjectId(req) ReadResultResponse(123L, makeFinished(breakdownResult), breakdowns.head._2) } case _ => fail(s"Unknown input: $input") } HttpResponse.ok(response.toI2b2String) } } val adapter: WithHiveCredentialsAdapter = makeAdapter(dao, new MightWorkMockHttpClient(AbstractQueryRetrievalTestCase.hiveCredentials)) def getResults = doGetResults(adapter) getResults.isInstanceOf[ErrorResponse] should be(true) dao.insertCountResult(idsByResultType(PATIENT_COUNT_XML).head, setSize, obfSetSize) dao.insertBreakdownResults(idsByResultType, breakdowns, obfscBreakdowns) //The query shouldn't be 'done', since its status is PROCESSING dao.findResultsFor(shrineNetworkQueryId).get.count.statusType should be(QueryResult.StatusType.Processing) //Now, calling processRequest (via getResults) should cause the query to be re-retrieved from the CRC val result = getResults.asInstanceOf[R] //Which should cause the query to be re-stored with a 'done' status (since that's what our mock CRC returns) val expectedStatusType = if (countQueryShouldWork) QueryResult.StatusType.Finished else QueryResult.StatusType.Processing dao.findResultsFor(shrineNetworkQueryId).get.count.statusType should be(expectedStatusType) if (!countQueryShouldWork) { result.isInstanceOf[ErrorResponse] should be(true) } else { val Some((actualNetworkQueryId, actualQueryResult)) = extractor(result) actualNetworkQueryId should equal(shrineNetworkQueryId) import ObfuscatorTest.within3 actualQueryResult.resultType should equal(Some(PATIENT_COUNT_XML)) within3(setSize, actualQueryResult.setSize) should be(true) actualQueryResult.description should be(Some("results from node X")) actualQueryResult.statusType should equal(QueryResult.StatusType.Finished) actualQueryResult.statusMessage should be(Some(QueryResult.StatusType.Finished.name)) actualQueryResult.breakdowns.foreach { case (rt, I2b2ResultEnvelope(_, data)) => { data.forall { case (key, value) => within3(value, breakdowns.get(rt).get.data.get(key).get) } } } for { startDate <- actualQueryResult.startDate endDate <- actualQueryResult.endDate } { val actualElapsed = toMillis(endDate) - toMillis(startDate) actualElapsed should equal(elapsed) } } } def doTestProcessRequestQueuedQuery: Unit = afterCreatingTables { import ResultOutputType._ import XmlDateHelper.now val startDate = now val elapsed = 100L val endDate = { import XmlGcEnrichments._ import scala.concurrent.duration._ startDate + elapsed.milliseconds } val countResultId = 456L val incompleteCountResult = QueryResult(-1L, -1L, Some(PATIENT_COUNT_XML), -1L, Option(startDate), Option(endDate), Some("results from node X"), QueryResult.StatusType.Queued, None) dao.inTransaction { val insertedQueryId = dao.insertQuery(localMasterId, shrineNetworkQueryId, authn, fooQuery, isFlagged = false, hasBeenRun = false, flagMessage = None) //NB: We need to insert dummy QueryResult and Count records so that calls to StoredQueries.retrieve() in //AbstractReadQueryResultAdapter, called when retrieving results for previously-queued-or-incomplete //queries, will work. val insertedQueryResultIds = dao.insertQueryResults(insertedQueryId, Seq(incompleteCountResult)) val countQueryResultId = insertedQueryResultIds(ResultOutputType.PATIENT_COUNT_XML).head dao.insertCountResult(countQueryResultId, -1L, -1L) } val queryStartDate = now object MockHttpClient extends HttpClient { override def post(input: String, url: String): HttpResponse = ??? } val adapter: WithHiveCredentialsAdapter = makeAdapter(dao, MockHttpClient) def getResults = doGetResults(adapter) getResults.isInstanceOf[ErrorResponse] should be(true) //The query shouldn't be 'done', since its status is QUEUED dao.findResultsFor(shrineNetworkQueryId).get.count.statusType should be(QueryResult.StatusType.Queued) //Now, calling processRequest (via getResults) should NOT cause the query to be re-retrieved from the CRC, because the query was previously queued val result = getResults result.isInstanceOf[ErrorResponse] should be(true) dao.findResultsFor(shrineNetworkQueryId).get.count.statusType should be(QueryResult.StatusType.Queued) } def doTestProcessRequest = afterCreatingTables { val adapter = makeAdapter(dao, MockHttpClient) def getResults = doGetResults(adapter) getResults match { case errorResponse:ErrorResponse => errorResponse.problemDigest.codec should be (classOf[QueryNotFound].getName) case x => fail(s"Got $x, not an ErrorResponse") } val dbQueryId = dao.insertQuery(localMasterId, shrineNetworkQueryId, authn, fooQuery, isFlagged = false, hasBeenRun = false, flagMessage = None) getResults match { case errorResponse:ErrorResponse => errorResponse.problemDigest.codec should be (classOf[QueryResultNotAvailable].getName) case x => fail(s"Got $x, not an ErrorResponse") } import ResultOutputType._ import XmlDateHelper.now val breakdowns = Map( PATIENT_AGE_COUNT_XML -> I2b2ResultEnvelope(PATIENT_AGE_COUNT_XML, Map("a" -> 1L, "b" -> 2L)), PATIENT_GENDER_COUNT_XML -> I2b2ResultEnvelope(PATIENT_GENDER_COUNT_XML, Map("x" -> 3L, "y" -> 4L))) val obfscBreakdowns = breakdowns.mapValues(_.mapValues(_ + 1)) val startDate = now val elapsed = 100L val endDate = { import XmlGcEnrichments._ import scala.concurrent.duration._ startDate + elapsed.milliseconds } val countResult = QueryResult( resultId = 456L, instanceId = instanceId, resultType = Some(PATIENT_COUNT_XML), setSize = setSize, startDate = Option(startDate), endDate = Option(endDate), description = Some("results from node X"), statusType = QueryResult.StatusType.Finished, statusMessage = None, breakdowns = breakdowns ) val breakdownResults = breakdowns.map { case (resultType, data) => countResult.withBreakdowns(Map(resultType -> data)).withResultType(resultType) }.toSeq val queryStartDate = now val idsByResultType = dao.insertQueryResults(dbQueryId, countResult +: breakdownResults) getResults.isInstanceOf[ErrorResponse] should be(true) dao.insertCountResult(idsByResultType(PATIENT_COUNT_XML).head, setSize, obfSetSize) dao.insertBreakdownResults(idsByResultType, breakdowns, obfscBreakdowns) val result = getResults.asInstanceOf[R] val Some((actualNetworkQueryId, actualQueryResult)) = extractor(result) actualNetworkQueryId should equal(shrineNetworkQueryId) actualQueryResult.resultType should equal(Some(PATIENT_COUNT_XML)) actualQueryResult.setSize should equal(obfSetSize) actualQueryResult.description should be(None) //TODO: This is probably wrong actualQueryResult.statusType should equal(QueryResult.StatusType.Finished) actualQueryResult.statusMessage should be(None) actualQueryResult.breakdowns should equal(obfscBreakdowns) for { startDate <- actualQueryResult.startDate endDate <- actualQueryResult.endDate } { val actualElapsed = toMillis(endDate) - toMillis(startDate) actualElapsed should equal(elapsed) } } } object AbstractQueryRetrievalTestCase { val hiveCredentials = HiveCredentials("some-hive-domain", "hive-username", "hive-password", "hive-project") val doObfuscation = true def runQueryAdapter(dao: AdapterDao, poster: Poster): RunQueryAdapter = { val translator = new QueryDefinitionTranslator(new ExpressionTranslator(Map("foo" -> Set("bar")))) new RunQueryAdapter( poster, dao, AbstractQueryRetrievalTestCase.hiveCredentials, translator, 10000, doObfuscation, runQueriesImmediately = true, DefaultBreakdownResultOutputTypes.toSet, collectAdapterAudit = false ) } import scala.concurrent.duration._ final class BogusRequest extends ShrineRequest("fooProject", 1.second, null) { override val requestType = null protected override def i2b2MessageBody: NodeSeq = override def toXml = } } \ No newline at end of file diff --git a/adapter/adapter-service/src/test/scala/net/shrine/adapter/RunQueryAdapterTest.scala b/adapter/adapter-service/src/test/scala/net/shrine/adapter/RunQueryAdapterTest.scala index b87a6e70a..f094d5b47 100644 --- a/adapter/adapter-service/src/test/scala/net/shrine/adapter/RunQueryAdapterTest.scala +++ b/adapter/adapter-service/src/test/scala/net/shrine/adapter/RunQueryAdapterTest.scala @@ -1,965 +1,965 @@ package net.shrine.adapter -import net.shrine.problem.TestProblem +import net.shrine.problem.{ProblemSources, AbstractProblem, TestProblem} import scala.concurrent.duration.DurationInt import org.junit.Test import net.shrine.util.ShouldMatchersForJUnit import ObfuscatorTest.within3 import net.shrine.adapter.dao.AdapterDao import net.shrine.adapter.dao.squeryl.AbstractSquerylAdapterTest import net.shrine.adapter.translators.ExpressionTranslator import net.shrine.adapter.translators.QueryDefinitionTranslator import net.shrine.client.HttpClient import net.shrine.client.HttpResponse import net.shrine.client.Poster import net.shrine.protocol.{HiveCredentials, AuthenticationInfo, BroadcastMessage, CrcRequest, Credential, I2b2ResultEnvelope, QueryResult, RawCrcRunQueryResponse, ReadResultRequest, ReadResultResponse, ResultOutputType, RunQueryRequest, RunQueryResponse, ErrorResponse, BaseShrineResponse, DefaultBreakdownResultOutputTypes} import net.shrine.protocol.RawCrcRunQueryResponse.toQueryResultMap import net.shrine.protocol.DefaultBreakdownResultOutputTypes.PATIENT_AGE_COUNT_XML import net.shrine.protocol.ResultOutputType.PATIENT_COUNT_XML import net.shrine.protocol.DefaultBreakdownResultOutputTypes.PATIENT_GENDER_COUNT_XML import net.shrine.protocol.DefaultBreakdownResultOutputTypes.PATIENT_RACE_COUNT_XML import net.shrine.protocol.query.OccuranceLimited import net.shrine.protocol.query.Or import net.shrine.protocol.query.QueryDefinition import net.shrine.protocol.query.Term import net.shrine.util.XmlDateHelper import net.shrine.util.XmlUtil import scala.util.Success import net.shrine.dao.squeryl.SquerylEntryPoint import scala.concurrent.duration.Duration import net.shrine.adapter.dao.model.ShrineError import net.shrine.adapter.dao.model.QueryResultRow /** * @author Bill Simons * @author Clint Gilbert * @since 4/19/11 * @see http://cbmi.med.harvard.edu */ final class RunQueryAdapterTest extends AbstractSquerylAdapterTest with ShouldMatchersForJUnit { private val queryDef = QueryDefinition("foo", Term("foo")) private val broadcastMessageId = 1234563789L private val queryId = 123L private val expectedNetworkQueryId = 999L private val expectedLocalMasterId = queryId.toString private val masterId = 99L private val instanceId = 456L private val resultId = 42L private val projectId = "projectId" private val setSize = 17L private val xmlResultId = 98765L private val userId = "userId" private val groupId = "groupId" private val topicId = "some-topic-id-123-foo" private val topicName = "Topic Name" private val justCounts = Set(PATIENT_COUNT_XML) private val now = XmlDateHelper.now private val countQueryResult = QueryResult(resultId, instanceId, Some(PATIENT_COUNT_XML), setSize, Some(now), Some(now), None, QueryResult.StatusType.Finished, None) private val dummyBreakdownData = Map("x" -> 99L, "y" -> 42L, "z" -> 3000L) private val hiveCredentials = HiveCredentials("some-hive-domain", "hive-username", "hive-password", "hive-project") private val authn = AuthenticationInfo("some-domain", "username", Credential("jksafhkjaf", false)) private val adapterLockoutThreshold = 99 private val altI2b2ErrorXml = XmlUtil.stripWhitespace { 1.1 2.4 edu.harvard.i2b2.crc 1.5 i2b2 Hive i2b2_QueryTool 0.2 i2b2 Hive 1 i2b2 Log information DONE Query result instance id 3126 not found }.toString private val otherNetworkId: Long = 12345L @Test def testProcessRawCrcRunQueryResponseCountQueryOnly: Unit = afterCreatingTables{ val outputTypes = Set(PATIENT_COUNT_XML) val translator = new QueryDefinitionTranslator(new ExpressionTranslator(Map("network" -> Set("local1a", "local1b")))) val adapter = new RunQueryAdapter( Poster("crc-url", null), dao, hiveCredentials, translator, adapterLockoutThreshold, doObfuscation = false, runQueriesImmediately = true, breakdownTypes = DefaultBreakdownResultOutputTypes.toSet, collectAdapterAudit = false ) val request = RunQueryRequest(projectId, 1.second, authn, expectedNetworkQueryId, Option(topicId), Option(topicName), outputTypes, queryDef) val networkAuthn = AuthenticationInfo("some-domain", "username", Credential("sadasdasdasd", false)) val broadcastMessage = BroadcastMessage(queryId, networkAuthn, request) val rawRunQueryResponse = RawCrcRunQueryResponse( queryId = queryId, createDate = XmlDateHelper.now, userId = request.authn.username, groupId = request.authn.domain, requestXml = request.queryDefinition, queryInstanceId = otherNetworkId, singleNodeResults = toQueryResultMap(Seq(countQueryResult))) val resp = adapter.processRawCrcRunQueryResponse(networkAuthn, request, rawRunQueryResponse).asInstanceOf[RunQueryResponse] resp should not be (null) //Validate the response resp.createDate should not be(null) resp.groupId should be(request.authn.domain) resp.userId should be(request.authn.username) resp.queryId should be(queryId) resp.queryInstanceId should be(otherNetworkId) resp.requestXml should equal(request.queryDefinition) (countQueryResult eq resp.singleNodeResult) should be(false) within3(resp.singleNodeResult.setSize, countQueryResult.setSize) should be(true) resp.singleNodeResult.resultType.get should equal(PATIENT_COUNT_XML) resp.singleNodeResult.breakdowns should equal(Map.empty) //validate the DB val expectedNetworkTerm = queryDef.expr.get.asInstanceOf[Term] //We should have one row in the shrine_query table, for the query just performed val Seq(queryRow) = list(queryRows) { queryRow.dateCreated should not be (null) queryRow.domain should equal(request.authn.domain) queryRow.name should equal(queryDef.name) queryRow.localId should equal(expectedLocalMasterId) queryRow.networkId should equal(expectedNetworkQueryId) queryRow.username should equal(authn.username) queryRow.queryDefinition.expr.get should equal(expectedNetworkTerm) } //We should have one row in the count_result table, with the right obfuscated value, which is within the expected amount from the original count val Seq(countRow) = list(countResultRows) { countRow.creationDate should not be (null) countRow.originalValue should equal(countQueryResult.setSize) within3(countRow.obfuscatedValue, countRow.originalValue) should be(true) } } @Test def testProcessRawCrcRunQueryResponseCountAndBreakdownQuery: Unit = afterCreatingTables { val allBreakdownTypes = DefaultBreakdownResultOutputTypes.toSet val breakdownTypes = Seq(PATIENT_GENDER_COUNT_XML) val outputTypes = Set(PATIENT_COUNT_XML) ++ breakdownTypes val translator = new QueryDefinitionTranslator(new ExpressionTranslator(Map("network" -> Set("local1a", "local1b")))) val request = RunQueryRequest(projectId, 1.second, authn, expectedNetworkQueryId, Option(topicId), Option(topicName), outputTypes, queryDef) val networkAuthn = AuthenticationInfo("some-domain", "username", Credential("sadasdasdasd", false)) val broadcastMessage = BroadcastMessage(queryId, networkAuthn, request) val breakdownQueryResults = breakdownTypes.zipWithIndex.map { case (rt, i) => countQueryResult.withId(resultId + i + 1).withResultType(rt) } val singleNodeResults = toQueryResultMap(countQueryResult +: breakdownQueryResults) val rawRunQueryResponse = RawCrcRunQueryResponse( queryId = queryId, createDate = XmlDateHelper.now, userId = request.authn.username, groupId = request.authn.domain, requestXml = request.queryDefinition, queryInstanceId = otherNetworkId, singleNodeResults = singleNodeResults) //Set up our mock CRC val poster = Poster("crc-url", new HttpClient { def post(input: String, url: String): HttpResponse = HttpResponse.ok { (RunQueryRequest.fromI2b2String(allBreakdownTypes)(input) orElse ReadResultRequest.fromI2b2String(allBreakdownTypes)(input)).get match { case runQueryReq: RunQueryRequest => rawRunQueryResponse.toI2b2String case readResultReq: ReadResultRequest => ReadResultResponse(xmlResultId = 42L, metadata = breakdownQueryResults.head, data = I2b2ResultEnvelope(PATIENT_GENDER_COUNT_XML, dummyBreakdownData)).toI2b2String case _ => sys.error(s"Unknown request: '$input'") //Fail loudly } } }) val adapter = new RunQueryAdapter( poster, dao, hiveCredentials, translator, adapterLockoutThreshold, doObfuscation = false, runQueriesImmediately = true, breakdownTypes = DefaultBreakdownResultOutputTypes.toSet, collectAdapterAudit = false ) val resp = adapter.processRawCrcRunQueryResponse(networkAuthn, request, rawRunQueryResponse).asInstanceOf[RunQueryResponse] resp should not be (null) //Validate the response resp.createDate should not be(null) resp.groupId should be(request.authn.domain) resp.userId should be(request.authn.username) resp.queryId should be(queryId) resp.queryInstanceId should be(otherNetworkId) resp.requestXml should equal(request.queryDefinition) (countQueryResult eq resp.singleNodeResult) should be(false) within3(resp.singleNodeResult.setSize, countQueryResult.setSize) should be(true) resp.singleNodeResult.resultType.get should equal(PATIENT_COUNT_XML) resp.singleNodeResult.breakdowns.keySet should equal(Set(PATIENT_GENDER_COUNT_XML)) val breakdownEnvelope = resp.singleNodeResult.breakdowns.values.head breakdownEnvelope.resultType should equal(PATIENT_GENDER_COUNT_XML) breakdownEnvelope.data.keySet should equal(dummyBreakdownData.keySet) //All breakdowns are obfuscated for { (key, value) <- breakdownEnvelope.data } { within3(value, dummyBreakdownData(key)) should be(true) } //validate the DB val expectedNetworkTerm = queryDef.expr.get.asInstanceOf[Term] //We should have one row in the shrine_query table, for the query just performed val Seq(queryRow) = list(queryRows) { queryRow.dateCreated should not be (null) queryRow.domain should equal(request.authn.domain) queryRow.name should equal(queryDef.name) queryRow.localId should equal(expectedLocalMasterId) queryRow.networkId should equal(expectedNetworkQueryId) queryRow.username should equal(authn.username) queryRow.queryDefinition.expr.get should equal(expectedNetworkTerm) } //We should have one row in the count_result table, with the right obfuscated value, which is within the expected amount from the original count val Seq(countRow) = list(countResultRows) { countRow.creationDate should not be (null) countRow.originalValue should equal(countQueryResult.setSize) within3(countRow.obfuscatedValue, countRow.originalValue) should be(true) } val breakdownRows @ Seq(xRow, yRow, zRow) = list(breakdownResultRows) breakdownRows.map(_.dataKey).toSet should equal(dummyBreakdownData.keySet) within3(xRow.obfuscatedValue, xRow.originalValue) should be(true) xRow.originalValue should be(dummyBreakdownData(xRow.dataKey)) within3(yRow.obfuscatedValue, yRow.originalValue) should be(true) yRow.originalValue should be(dummyBreakdownData(yRow.dataKey)) within3(zRow.obfuscatedValue, zRow.originalValue) should be(true) zRow.originalValue should be(dummyBreakdownData(zRow.dataKey)) } //NB: See https://open.med.harvard.edu/jira/browse/SHRINE-745 @Test def testParseAltErrorXml { val adapter = new RunQueryAdapter( Poster("crc-url", null), null, hiveCredentials, null, adapterLockoutThreshold, doObfuscation = false, runQueriesImmediately = false, DefaultBreakdownResultOutputTypes.toSet, collectAdapterAudit = false ) val resp: ErrorResponse = adapter.parseShrineErrorResponseWithFallback(altI2b2ErrorXml).asInstanceOf[ErrorResponse] resp should not be (null) resp.errorMessage should be("Query result instance id 3126 not found") } @Test def testParseErrorXml { val xml = { 1.1 2.4 edu.harvard.i2b2.crc 1.4 i2b2 Hive i2b2web 1.4 i2b2 Hive 1 Demo Log information Message error connecting Project Management cell admin 0 0 CRC_QRY_runQueryInstance_fromQueryDefinition Age 0 1 0 0 1 2 Age \\i2b2\i2b2\Demographics\Age\ concept_dimension concept_path \i2b2\Demographics\Age\ T concept_cd false }.toString val adapter = new RunQueryAdapter( Poster("crc-url", null), null, hiveCredentials, null, adapterLockoutThreshold, doObfuscation = false, runQueriesImmediately = true, DefaultBreakdownResultOutputTypes.toSet, collectAdapterAudit = false ) val resp = adapter.parseShrineErrorResponseWithFallback(xml).asInstanceOf[ErrorResponse] resp should not be (null) resp.errorMessage should not be ("") } @Test def testObfuscateBreakdowns { val breakdown1 = I2b2ResultEnvelope(PATIENT_AGE_COUNT_XML, Map.empty) val breakdown2 = I2b2ResultEnvelope(PATIENT_GENDER_COUNT_XML, Map("foo" -> 123, "bar" -> 345)) val breakdown3 = I2b2ResultEnvelope(PATIENT_RACE_COUNT_XML, Map("x" -> 999, "y" -> 888)) val original = Map.empty ++ Seq(breakdown1, breakdown2, breakdown3).map(env => (env.resultType, env)) val obfuscated = RunQueryAdapter.obfuscateBreakdowns(original) original.keySet should equal(obfuscated.keySet) original.keySet.forall(resultType => original(resultType).data.keySet == obfuscated(resultType).data.keySet) should be(true) val localTerms = Set("local1a", "local1b") for { (resultType, origBreakdown) <- original mappings = Map("network" -> localTerms) translator = new QueryDefinitionTranslator(new ExpressionTranslator(mappings)) obfscBreakdown <- obfuscated.get(resultType) key <- origBreakdown.data.keySet } { (origBreakdown eq obfscBreakdown) should be(false) ObfuscatorTest.within3(origBreakdown.data(key), obfscBreakdown.data(key)) should be(true) } } @Test def testTranslateNetworkToLocalDoesntLeakCredentialsViaException: Unit = { val mappings = Map.empty[String, Set[String]] val translator = new QueryDefinitionTranslator(new ExpressionTranslator(mappings)) val adapter = new RunQueryAdapter( Poster("crc-url", MockHttpClient), null, null, translator, adapterLockoutThreshold, doObfuscation = false, runQueriesImmediately = true, DefaultBreakdownResultOutputTypes.toSet, collectAdapterAudit = false ) val queryDefinition = QueryDefinition("foo", Term("blah")) val authn = AuthenticationInfo("d", "u", Credential("p", false)) val req = RunQueryRequest("projectId", Duration.Inf, authn, otherNetworkId, None, None, Set.empty, queryDef) try { adapter.translateNetworkToLocal(req) fail("Expected an AdapterMappingException") } catch { case e: AdapterMappingException => { e.getMessage.contains(authn.rawToString) should be(false) e.getMessage.contains(AuthenticationInfo.elided.toString) should be(true) } } } @Test def testTranslateQueryDefinitionXml { val localTerms = Set("local1a", "local1b") val mappings = Map("network" -> localTerms) val translator = new QueryDefinitionTranslator(new ExpressionTranslator(mappings)) val adapter = new RunQueryAdapter( Poster("crc-url", MockHttpClient), null, null, translator, adapterLockoutThreshold, doObfuscation = false, runQueriesImmediately = true, DefaultBreakdownResultOutputTypes.toSet, collectAdapterAudit = false ) val queryDefinition = QueryDefinition("10-17 years old@14:39:20", OccuranceLimited(1, Term("network"))) val newDef = adapter.conceptTranslator.translate(queryDefinition) val expected = QueryDefinition("10-17 years old@14:39:20", Or(Term("local1a"), Term("local1b"))) newDef should equal(expected) } @Test def testQueuedRegularCountQuery: Unit = afterCreatingTables { val adapter = RunQueryAdapter( Poster("crc-url", MockHttpClient), dao, null, null, adapterLockoutThreshold, doObfuscation = false, runQueriesImmediately = false, DefaultBreakdownResultOutputTypes.toSet, collectAdapterAudit = false ) val networkAuthn = AuthenticationInfo("nd", "nu", Credential("np", false)) import scala.concurrent.duration._ val req = RunQueryRequest(projectId, 1.second, authn, expectedNetworkQueryId, Option(topicId), Option(topicName), Set(PATIENT_COUNT_XML), queryDef) val broadcastMessage = BroadcastMessage(queryId, networkAuthn, req) val resp = adapter.processRequest(broadcastMessage).asInstanceOf[RunQueryResponse] resp.groupId should equal(networkAuthn.domain) resp.createDate should not be (null) // :\ resp.queryId should equal(-1L) resp.queryInstanceId should equal(-1L) resp.requestXml should equal(queryDef) resp.userId should equal(networkAuthn.username) resp.singleNodeResult.breakdowns should equal(Map.empty) resp.singleNodeResult.description.isDefined should be(true) resp.singleNodeResult.elapsed should equal(Some(0L)) resp.singleNodeResult.endDate.isDefined should be(true) resp.singleNodeResult.startDate.isDefined should be(true) resp.singleNodeResult.instanceId should equal(-1L) resp.singleNodeResult.isError should be(false) resp.singleNodeResult.resultId should equal(-1L) resp.singleNodeResult.resultType should be(Some(PATIENT_COUNT_XML)) resp.singleNodeResult.setSize should equal(-1L) resp.singleNodeResult.statusMessage.isDefined should be(true) resp.singleNodeResult.statusType should be(QueryResult.StatusType.Held) resp.singleNodeResult.endDate.isDefined should be(true) val Some(storedQuery) = dao.findQueryByNetworkId(expectedNetworkQueryId) storedQuery.dateCreated should not be (null) // :\ storedQuery.domain should equal(networkAuthn.domain) storedQuery.isFlagged should equal(false) storedQuery.localId should equal(-1L.toString) storedQuery.name should equal(queryDef.name) storedQuery.networkId should equal(expectedNetworkQueryId) storedQuery.queryDefinition should equal(queryDef) storedQuery.username should equal(networkAuthn.username) } private def doTestRegularCountQuery(status: QueryResult.StatusType, count: Long) = afterCreatingTables { require(!status.isError) val countQueryResultToUse = countQueryResult.copy(statusType = status, setSize = count) val outputTypes = justCounts val resp = doQuery(outputTypes) { import RawCrcRunQueryResponse.toQueryResultMap RawCrcRunQueryResponse(queryId, now, userId, groupId, queryDef, instanceId, toQueryResultMap(Seq(countQueryResultToUse))).toI2b2String }.asInstanceOf[RunQueryResponse] doBasicRunQueryResponseTest(resp) val firstResult = resp.results.head resp.results should equal(Seq(firstResult)) val Some(savedQuery) = dao.findResultsFor(expectedNetworkQueryId) savedQuery.wasRun should equal(true) savedQuery.isFlagged should equal(false) savedQuery.networkQueryId should equal(expectedNetworkQueryId) savedQuery.breakdowns should equal(Nil) savedQuery.count.creationDate should not be (null) savedQuery.count.localId should equal(countQueryResultToUse.resultId) //savedQuery.count.resultId should equal(resultId) TODO: REVISIT savedQuery.count.statusType should equal(status) if (status.isDone && !status.isError) { savedQuery.count.data.get.startDate should not be (null) savedQuery.count.data.get.endDate should not be (null) savedQuery.count.data.get.originalValue should be(count) ObfuscatorTest.within3(savedQuery.count.data.get.obfuscatedValue, count) should be(true) } else { savedQuery.count.data should be(None) } } @Test def testRegularCountQuery = doTestRegularCountQuery(QueryResult.StatusType.Finished, countQueryResult.setSize) @Test def testRegularCountQueryComesBackProcessing = doTestRegularCountQuery(QueryResult.StatusType.Processing, -1L) @Test def testRegularCountQueryComesBackQueued = doTestRegularCountQuery(QueryResult.StatusType.Queued, -1L) @Test def testRegularCountQueryComesBackError = afterCreatingTables { - val errorQueryResult = QueryResult.errorResult(Some("some-description"), "some-status-message",TestProblem) + val errorQueryResult = QueryResult.errorResult(Some("some-description"), "some-status-message",TestProblem()) val outputTypes = justCounts val resp = doQuery(outputTypes) { import RawCrcRunQueryResponse.toQueryResultMap RawCrcRunQueryResponse(queryId, now, userId, groupId, queryDef, instanceId, toQueryResultMap(Seq(errorQueryResult))).toI2b2String } doBasicRunQueryResponseTest(resp) //TODO: Why are status and description messages from CRC dropped when unmarshalling QueryResults? //resp.results should equal(Seq(errorQueryResult)) resp.asInstanceOf[RunQueryResponse].results.head.statusType should be(QueryResult.StatusType.Error) dao.findResultsFor(expectedNetworkQueryId) should be(None) val Some(savedQueryRow) = dao.findQueryByNetworkId(expectedNetworkQueryId) val Seq(queryResultRow: QueryResultRow) = { import SquerylEntryPoint._ implicit val breakdownTypes = DefaultBreakdownResultOutputTypes.toSet inTransaction { from(tables.queryResults) { row => where(row.queryId === savedQueryRow.id). select(row.toQueryResultRow) }.toSeq } } val Seq(errorRow: ShrineError) = { import SquerylEntryPoint._ inTransaction { from(tables.errorResults) { row => where(row.resultId === queryResultRow.id). select(row.toShrineError) }.toSeq } } errorRow should not be (null) //TODO: ErrorMessage //errorRow.message should equal(errorQueryResult.statusMessage) } private def doTestBreakdownsAreObfuscated(result: QueryResult): Unit = { result.breakdowns.values.map(_.data).foreach { actualBreakdowns => actualBreakdowns.keySet should equal(dummyBreakdownData.keySet) for { breakdownName <- actualBreakdowns.keySet } { within3(actualBreakdowns(breakdownName), dummyBreakdownData(breakdownName)) should be(true) } } } @Test def testGetBreakdownsWithRegularCountQuery { val breakdowns = DefaultBreakdownResultOutputTypes.values.map(breakdownFor) val resp = doTestGetBreakdowns(breakdowns) val firstResult = resp.results.head firstResult.resultType should equal(Some(PATIENT_COUNT_XML)) firstResult.setSize should equal(setSize) firstResult.description should equal(None) firstResult.breakdowns.keySet should equal(DefaultBreakdownResultOutputTypes.toSet) //NB: Verify that breakdowns are obfuscated doTestBreakdownsAreObfuscated(firstResult) resp.results.size should equal(1) } @Test def testGetBreakdownsSomeFailures { val resultTypesExpectedToSucceed = Seq(PATIENT_AGE_COUNT_XML, PATIENT_GENDER_COUNT_XML) val breakdowns = resultTypesExpectedToSucceed.map(breakdownFor) val resp = doTestGetBreakdowns(breakdowns) val firstResult = resp.results.head firstResult.resultType should equal(Some(PATIENT_COUNT_XML)) firstResult.setSize should equal(setSize) firstResult.description should equal(None) firstResult.breakdowns.keySet should equal(resultTypesExpectedToSucceed.toSet) //NB: Verify that breakdowns are obfuscated doTestBreakdownsAreObfuscated(firstResult) resp.results.size should equal(1) } @Test def testErrorResponsesArePassedThrough: Unit = { - val errorResponse = ErrorResponse("blarg!") + val errorResponse = ErrorResponse(TestProblem(summary = "blarg!")) val resp = doQuery(Set(PATIENT_COUNT_XML)) { errorResponse.toI2b2String } resp should equal(errorResponse) } private def breakdownFor(resultType: ResultOutputType) = I2b2ResultEnvelope(resultType, dummyBreakdownData) private def doTestGetBreakdowns(successfulBreakdowns: Seq[I2b2ResultEnvelope]): RunQueryResponse = { val outputTypes = justCounts ++ DefaultBreakdownResultOutputTypes.toSet val resp = doQueryThatReturnsSpecifiedBreakdowns(outputTypes, successfulBreakdowns) doBasicRunQueryResponseTest(resp) resp } private def doBasicRunQueryResponseTest(r: BaseShrineResponse) { val resp = r.asInstanceOf[RunQueryResponse] resp.createDate should equal(now) resp.groupId should equal(groupId) resp.queryId should equal(queryId) resp.queryInstanceId should equal(instanceId) resp.queryName should equal(queryDef.name) resp.requestXml should equal(queryDef) } private def doQueryThatReturnsSpecifiedBreakdowns(outputTypes: Set[ResultOutputType], successfulBreakdowns: Seq[I2b2ResultEnvelope]): RunQueryResponse = afterCreatingTablesReturn { val breakdownQueryResults = DefaultBreakdownResultOutputTypes.values.zipWithIndex.map { case (rt, i) => countQueryResult.withId(resultId + i + 1).withResultType(rt) } //Need this rigamarole to ensure that resultIds line up such that the type of breakdown the adapter asks for //(PATIENT_AGE_COUNT_XML, etc) is what the mock HttpClient actually returns. Here, we build up maps of QueryResults //and I2b2ResultEnvelopes, keyed on resultIds generated in the previous expression, to use to look up values to use //to build ReadResultResponses val successfulBreakdownsByType = successfulBreakdowns.map(e => e.resultType -> e).toMap val successfulBreakdownTypes = successfulBreakdownsByType.keySet val breakdownQueryResultsByResultId = breakdownQueryResults.collect { case qr if successfulBreakdownTypes(qr.resultType.get) => qr.resultId -> qr }.toMap val breakdownsToBeReturnedByResultId = breakdownQueryResultsByResultId.map { case (resultId, queryResult) => (resultId, successfulBreakdownsByType(queryResult.resultType.get)) } val expectedLocalTerm = Term("bar") val httpClient = new HttpClient { override def post(input: String, url: String): HttpResponse = { val resp = CrcRequest.fromI2b2String(DefaultBreakdownResultOutputTypes.toSet)(input) match { case Success(req: RunQueryRequest) => { //NB: Terms should be translated req.queryDefinition.expr.get should equal(expectedLocalTerm) //Credentials should be "translated" req.authn.username should equal(hiveCredentials.username) req.authn.domain should equal(hiveCredentials.domain) //I2b2 Project ID should be translated req.projectId should equal(hiveCredentials.projectId) val queryResultMap = RawCrcRunQueryResponse.toQueryResultMap(countQueryResult +: breakdownQueryResults) RawCrcRunQueryResponse(queryId, now, "userId", "groupId", queryDef, instanceId, queryResultMap) } //NB: return a ReadResultResponse with new breakdown data each time, but will throw if the asked-for breakdown //is not one of the ones passed to the enclosing method, simulating an error calling the CRC case Success(req: ReadResultRequest) => { val resultId = req.localResultId.toLong ReadResultResponse(xmlResultId, breakdownQueryResultsByResultId(resultId), breakdownsToBeReturnedByResultId(resultId)) } case _ => ??? //fail loudly } HttpResponse.ok(resp.toI2b2String) } } val result = doQuery(outputTypes, dao, httpClient) validateDb(successfulBreakdowns, breakdownQueryResultsByResultId) result.asInstanceOf[RunQueryResponse] } private def validateDb(breakdownsReturned: Seq[I2b2ResultEnvelope], breakdownQueryResultsByResultId: Map[Long, QueryResult]) { val expectedNetworkTerm = Term("foo") //We should have one row in the shrine_query table, for the query just performed val queryRow = first(queryRows) { queryRow.dateCreated should not be (null) queryRow.domain should equal(authn.domain) queryRow.name should equal(queryDef.name) queryRow.localId should equal(expectedLocalMasterId) queryRow.networkId should equal(expectedNetworkQueryId) queryRow.username should equal(authn.username) queryRow.queryDefinition.expr.get should equal(expectedNetworkTerm) } list(queryRows).size should equal(1) //We should have one row in the count_result table, with the right obfuscated value, which is within the expected amount from the original count val countRow = first(countResultRows) { countRow.creationDate should not be (null) countRow.originalValue should equal(countQueryResult.setSize) within3(countRow.obfuscatedValue, countQueryResult.setSize) should be(true) within3(countRow.obfuscatedValue, countRow.originalValue) should be(true) } list(countResultRows).size should equal(1) //We should have 5 rows in the query_result table, one for the count result and one for each of the 4 requested breakdown types val queryResults = list(queryResultRows) { val countQueryResultRow = queryResults.find(_.resultType == PATIENT_COUNT_XML).get countQueryResultRow.localId should equal(countQueryResult.resultId) countQueryResultRow.queryId should equal(queryRow.id) val resultIdsByResultType = breakdownQueryResultsByResultId.map { case (resultId, queryResult) => queryResult.resultType.get -> resultId }.toMap for (breakdownType <- DefaultBreakdownResultOutputTypes.values) { val breakdownQueryResultRow = queryResults.find(_.resultType == breakdownType).get breakdownQueryResultRow.queryId should equal(queryRow.id) //We'll have a result id if this breakdown type didn't fail if (resultIdsByResultType.contains(breakdownQueryResultRow.resultType)) { breakdownQueryResultRow.localId should equal(resultIdsByResultType(breakdownQueryResultRow.resultType)) } } } queryResults.size should equal(5) val returnedBreakdownTypes = breakdownsReturned.map(_.resultType).toSet val notReturnedBreakdownTypes = DefaultBreakdownResultOutputTypes.toSet -- returnedBreakdownTypes val errorResults = list(errorResultRows) //We should have a row in the error_result table for each breakdown that COULD NOT be retrieved { for { queryResult <- queryResults if notReturnedBreakdownTypes.contains(queryResult.resultType) resultType = queryResult.resultType resultId = queryResult.id } { errorResults.find(_.resultId == resultId).isDefined should be(true) } } errorResults.size should equal(notReturnedBreakdownTypes.size) //We should have properly-obfuscated rows in the breakdown_result table for each of the breakdown types that COULD be retrieved val breakdownResults = list(breakdownResultRows) val bdrs = breakdownResults.toIndexedSeq { for { queryResult <- queryResults if returnedBreakdownTypes.contains(queryResult.resultType) resultType = queryResult.resultType resultId = queryResult.id } { //Find all the rows for a particular breakdown type val rowsWithType = breakdownResults.filter(_.resultId == resultId) //Combining the rows should give the expected dummy data rowsWithType.map(row => row.dataKey -> row.originalValue).toMap should equal(dummyBreakdownData) for (breakdownRow <- rowsWithType) { within3(breakdownRow.obfuscatedValue, dummyBreakdownData(breakdownRow.dataKey)) should be(true) } } } } private def doQuery(outputTypes: Set[ResultOutputType])(i2b2XmlToReturn: => String): BaseShrineResponse = { doQuery(outputTypes, dao, MockHttpClient(i2b2XmlToReturn)) } private def doQuery(outputTypes: Set[ResultOutputType], adapterDao: AdapterDao, httpClient: HttpClient): BaseShrineResponse = { val translator = new QueryDefinitionTranslator(new ExpressionTranslator(Map("foo" -> Set("bar")))) //NB: Don't obfuscate, for simpler testing val adapter = new RunQueryAdapter( Poster("crc-url", httpClient), adapterDao, hiveCredentials, translator, adapterLockoutThreshold, doObfuscation = false, runQueriesImmediately = true, DefaultBreakdownResultOutputTypes.toSet, collectAdapterAudit = false ) import scala.concurrent.duration._ val req = RunQueryRequest(projectId, 1.second, authn, expectedNetworkQueryId, Option(topicId), Option(topicName), outputTypes, queryDef) val networkAuthn = AuthenticationInfo("some-domain", "username", Credential("sadasdasdasd", false)) val broadcastMessage = BroadcastMessage(queryId, networkAuthn, req) adapter.processRequest(broadcastMessage) } } \ No newline at end of file diff --git a/adapter/adapter-service/src/test/scala/net/shrine/adapter/dao/model/ShrineErrorTest.scala b/adapter/adapter-service/src/test/scala/net/shrine/adapter/dao/model/ShrineErrorTest.scala index ab7c7305b..49182a56e 100644 --- a/adapter/adapter-service/src/test/scala/net/shrine/adapter/dao/model/ShrineErrorTest.scala +++ b/adapter/adapter-service/src/test/scala/net/shrine/adapter/dao/model/ShrineErrorTest.scala @@ -1,20 +1,20 @@ package net.shrine.adapter.dao.model import net.shrine.util.ShouldMatchersForJUnit import net.shrine.problem.TestProblem import net.shrine.protocol.QueryResult /** * @author clint * @since Nov 1, 2012 */ final class ShrineErrorTest extends ShouldMatchersForJUnit { def testToQueryResult() { val message = "something broke" - val testProblem = TestProblem + val testProblem = TestProblem() val tpd = testProblem.toDigest val error = ShrineError(1, 123, message,tpd.codec,tpd.stampText,tpd.summary,tpd.description,tpd.detailsXml) - error.toQueryResult should equal(QueryResult.errorResult(Some(message), QueryResult.StatusType.Error.name,TestProblem)) + error.toQueryResult should equal(QueryResult.errorResult(Some(message), QueryResult.StatusType.Error.name,testProblem)) } } \ No newline at end of file diff --git a/adapter/adapter-service/src/test/scala/net/shrine/adapter/dao/model/ShrineQueryResultTest.scala b/adapter/adapter-service/src/test/scala/net/shrine/adapter/dao/model/ShrineQueryResultTest.scala index 57af254f7..de860b50f 100644 --- a/adapter/adapter-service/src/test/scala/net/shrine/adapter/dao/model/ShrineQueryResultTest.scala +++ b/adapter/adapter-service/src/test/scala/net/shrine/adapter/dao/model/ShrineQueryResultTest.scala @@ -1,96 +1,96 @@ package net.shrine.adapter.dao.model import net.shrine.problem.TestProblem import net.shrine.util.ShouldMatchersForJUnit import org.junit.Test import net.shrine.protocol.ResultOutputType import net.shrine.protocol.QueryResult.StatusType import net.shrine.util.XmlDateHelper import net.shrine.protocol.QueryResult import net.shrine.protocol.I2b2ResultEnvelope import net.shrine.protocol.query.{QueryDefinition, Term} import net.shrine.protocol.DefaultBreakdownResultOutputTypes /** * @author clint * @since Nov 1, 2012 */ final class ShrineQueryResultTest extends ShouldMatchersForJUnit { import ResultOutputType._ import DefaultBreakdownResultOutputTypes._ private val queryId = 999 private def someId = scala.util.Random.nextInt private def queryResultRow(resultType: ResultOutputType) = QueryResultRow( someId, someId.toLong, queryId, resultType, (if (resultType.isError) StatusType.Error else StatusType.Finished), (if (resultType.isError) None else Some(100)), XmlDateHelper.now) private val countQueryResultRow = queryResultRow(PATIENT_COUNT_XML) private val breakdownQueryResultRow1 = queryResultRow(PATIENT_AGE_COUNT_XML) private val breakdownQueryResultRow2 = queryResultRow(PATIENT_GENDER_COUNT_XML) private val errorQueryResultRow1 = queryResultRow(ERROR) private val errorQueryResultRow2 = queryResultRow(ERROR) private val topicId = "some-topic-id" private val flagMessage = Some("alksjdkalsjdalsjd") private val queryName = "some-query" private val queryExpr = Term("foo") private val queryDefinition = QueryDefinition(queryName,queryExpr) private val queryRow = ShrineQuery(123, "48573498739845", 392874L, queryName, "some-user", "some-domain", XmlDateHelper.now, isFlagged = true, flagMessage = flagMessage,queryDefinition = queryDefinition) private val resultRows = Seq(countQueryResultRow, breakdownQueryResultRow1, breakdownQueryResultRow2, errorQueryResultRow1, errorQueryResultRow2) private val countRow = CountRow(someId, countQueryResultRow.id, 99, 100, XmlDateHelper.now) private val breakdownRows = Map( PATIENT_AGE_COUNT_XML -> Seq(BreakdownResultRow(someId, breakdownQueryResultRow1.id, "x", 1, 2), BreakdownResultRow(someId, breakdownQueryResultRow1.id, "y", 2, 3)), PATIENT_GENDER_COUNT_XML -> Seq(BreakdownResultRow(someId, breakdownQueryResultRow2.id, "a", 9, 10), BreakdownResultRow(someId, breakdownQueryResultRow2.id, "b", 10, 11))) - private val pd = TestProblem.toDigest + private val pd = TestProblem().toDigest private val errorRows = Seq(ShrineError(someId, errorQueryResultRow1.id, "foo", pd.codec,pd.stampText,pd.summary,pd.description,pd.detailsXml), ShrineError(someId, errorQueryResultRow2.id, "bar", pd.codec,pd.stampText,pd.summary,pd.description,pd.detailsXml)) @Test def testToQueryResults { val Some(shrineQueryResult) = ShrineQueryResult.fromRows(queryRow, resultRows, countRow, breakdownRows, errorRows) for (doObfuscation <- Seq(true, false)) { def obfuscate(i: Int) = if (doObfuscation) i + 1 else i val expected = Count.fromRows(countQueryResultRow, countRow).toQueryResult.map(_.withBreakdowns(Map( PATIENT_AGE_COUNT_XML -> I2b2ResultEnvelope(PATIENT_AGE_COUNT_XML, Map("x" -> obfuscate(1), "y" -> obfuscate(2))), PATIENT_GENDER_COUNT_XML -> I2b2ResultEnvelope(PATIENT_GENDER_COUNT_XML, Map("a" -> obfuscate(9), "b" -> obfuscate(10)))))) shrineQueryResult.toQueryResults(doObfuscation) should equal(expected) } } @Test def testFromRows { ShrineQueryResult.fromRows(null, Nil, countRow, breakdownRows, errorRows) should be(None) val Some(shrineQueryResult) = ShrineQueryResult.fromRows(queryRow, resultRows, countRow, breakdownRows, errorRows) shrineQueryResult.isFlagged should be(queryRow.isFlagged) shrineQueryResult.flagMessage should be(flagMessage) shrineQueryResult.count should equal(Count.fromRows(countQueryResultRow, countRow)) shrineQueryResult.errors should equal(errorRows) shrineQueryResult.breakdowns.toSet should equal(Set( Breakdown(breakdownQueryResultRow1.id, breakdownQueryResultRow1.localId, PATIENT_AGE_COUNT_XML, Map("x" -> ObfuscatedPair(1, 2), "y" -> ObfuscatedPair(2, 3))), Breakdown(breakdownQueryResultRow2.id, breakdownQueryResultRow2.localId, PATIENT_GENDER_COUNT_XML, Map("a" -> ObfuscatedPair(9, 10), "b" -> ObfuscatedPair(10, 11))))) } } \ No newline at end of file diff --git a/adapter/adapter-service/src/test/scala/net/shrine/adapter/dao/squeryl/SquerylAdapterDaoTest.scala b/adapter/adapter-service/src/test/scala/net/shrine/adapter/dao/squeryl/SquerylAdapterDaoTest.scala index 07d7c184e..b882d394b 100644 --- a/adapter/adapter-service/src/test/scala/net/shrine/adapter/dao/squeryl/SquerylAdapterDaoTest.scala +++ b/adapter/adapter-service/src/test/scala/net/shrine/adapter/dao/squeryl/SquerylAdapterDaoTest.scala @@ -1,669 +1,669 @@ package net.shrine.adapter.dao.squeryl import net.shrine.problem.TestProblem import net.shrine.util.ShouldMatchersForJUnit import net.shrine.protocol.AuthenticationInfo import net.shrine.protocol.query.QueryDefinition import net.shrine.protocol.Credential import net.shrine.util.XmlDateHelper import net.shrine.protocol.query.Term import net.shrine.protocol.ResultOutputType import net.shrine.protocol.I2b2ResultEnvelope import net.shrine.protocol.QueryResult import net.shrine.protocol.RawCrcRunQueryResponse import org.junit.Test import net.shrine.adapter.dao.model.ShrineQuery import net.shrine.adapter.dao.model.ShrineQueryResult import net.shrine.adapter.dao.model.ObfuscatedPair import net.shrine.adapter.dao.model.QueryResultRow import net.shrine.protocol.DefaultBreakdownResultOutputTypes import net.shrine.adapter.dao.model.squeryl.SquerylShrineQuery import net.shrine.dao.DateHelpers /** * @author clint * @since May 24, 2013 */ final class SquerylAdapterDaoTest extends AbstractSquerylAdapterTest with ShouldMatchersForJUnit { private val authn = AuthenticationInfo("some-domain", "some-user", Credential("laskhdakslhd", false)) private val queryDef1 = QueryDefinition("foo", Term("blarg")) private def now = Option(XmlDateHelper.now) import ResultOutputType._ import DefaultBreakdownResultOutputTypes._ private val topicId = "some-topic-id" private val count = 999L private val resultId = 1L private val instanceId = 2L private val desc = Some("xyz") private val message1 = "something bad happened" private val message2 = "blah blah blah" private val onlyAgeBreakdown = Map(PATIENT_AGE_COUNT_XML -> I2b2ResultEnvelope(PATIENT_AGE_COUNT_XML, Map("x" -> 1, "y" -> 2))) private val onlyGenderBreakdown = Map(PATIENT_GENDER_COUNT_XML -> I2b2ResultEnvelope(PATIENT_GENDER_COUNT_XML, Map("a" -> 123, "b" -> 456))) private val breakdownsByType = onlyAgeBreakdown ++ onlyGenderBreakdown private val networkQueryId1 = 123L private val networkQueryId2 = 456L private val networkQueryId3 = 999L private val masterId1 = "abc" private val masterId2 = "def" private val masterId3 = "ghi" private val countQueryResult = QueryResult(resultId, instanceId, Some(PATIENT_COUNT_XML), count, now, now, desc, QueryResult.StatusType.Finished, None) - private val errorQueryResult1 = QueryResult.errorResult(desc, message1,TestProblem) - private val errorQueryResult2 = QueryResult.errorResult(desc, message2,TestProblem) + private val errorQueryResult1 = QueryResult.errorResult(desc, message1,TestProblem()) + private val errorQueryResult2 = QueryResult.errorResult(desc, message2,TestProblem()) private val breakdownQueryResult1 = QueryResult(resultId, instanceId, Some(PATIENT_AGE_COUNT_XML), countQueryResult.setSize, now, now, desc, QueryResult.StatusType.Finished, None, breakdowns = onlyAgeBreakdown) private val breakdownQueryResult2 = QueryResult(resultId, instanceId, Some(PATIENT_GENDER_COUNT_XML), countQueryResult.setSize, now, now, desc, QueryResult.StatusType.Finished, None, breakdowns = onlyGenderBreakdown) import RawCrcRunQueryResponse.toQueryResultMap private val countRunQueryResponse = RawCrcRunQueryResponse(networkQueryId1, now.get, authn.username, authn.domain, queryDef1, instanceId, toQueryResultMap(Seq(countQueryResult))) private val onlyErrorsRunQueryResponse = countRunQueryResponse.withResults(Seq(errorQueryResult1, errorQueryResult2)) private val countAndBreakdownsRunQueryResponse = countRunQueryResponse.withResults(Seq(countQueryResult, breakdownQueryResult1, breakdownQueryResult2)) private val onlyBreakdownsRunQueryResponse = countRunQueryResponse.withResults(Seq(breakdownQueryResult1, breakdownQueryResult2)) @Test def testFindQueryByNetworkIdNullQueryDefNonNullQueryExpr: Unit = afterCreatingTables { val id = 123 val localId = "localId" val networkQueryId = 42L val queryName = "some-query" val user = "u" val domain = "d" val expr = Term("""\\FOO\BAR\BAZ""") val dateCreated = XmlDateHelper.now val isFlagged = true val flagMessage = Some("fm") val hasBeenRun = true val squerylShrineQuery = SquerylShrineQuery( id, localId, networkQueryId, queryName, user, domain, Some(expr.toXmlString), DateHelpers.toTimestamp(dateCreated), isFlagged, flagMessage, hasBeenRun, queryXml = None) tables.shrineQueries.insert(squerylShrineQuery) val shrineQuery = squerylShrineQuery.toShrineQuery shrineQuery.dateCreated should equal(dateCreated) shrineQuery.domain should equal(domain) shrineQuery.username should equal(user) shrineQuery.flagMessage should equal(flagMessage) shrineQuery.id should equal(1) shrineQuery.isFlagged should equal(isFlagged) shrineQuery.localId should equal(localId) shrineQuery.name should equal(queryName) shrineQuery.networkId should equal(networkQueryId) shrineQuery.queryDefinition should equal(QueryDefinition(queryName, expr)) val fromDb = dao.findQueryByNetworkId(networkQueryId).get fromDb should equal(shrineQuery) } @Test def testFindPreviousQueries = afterCreatingTables { dao.findRecentQueries(0) should equal(Nil) dao.findRecentQueries(1) should equal(Nil) dao.insertQuery(masterId1, networkQueryId1, authn, queryDef1, isFlagged = false, hasBeenRun = true, flagMessage = None) //Make next query happen 10 milliseconds later, so we can distinguish it from the one we just inserted //(java.sql.Timestamps have 1ms resolution, it appears?) Thread.sleep(10) dao.findRecentQueries(0) should equal(Nil) { val Seq(query) = dao.findRecentQueries(1) query.networkId should equal(networkQueryId1) } dao.insertQuery(masterId2, networkQueryId2, authn, queryDef1, isFlagged = false, hasBeenRun = true, flagMessage = None) //Make next query happen 10 milliseconds later, so we can distinguish it from the one we just inserted //(java.sql.Timestamps, or perhaps XmlGregorianCalendars, have 1ms resolution?) Thread.sleep(10) dao.insertQuery(masterId3, networkQueryId3, authn, queryDef1, isFlagged = false, hasBeenRun = true, flagMessage = None) //Should come back newest-queries-first dao.findRecentQueries(2).map(_.networkId) should equal(Seq(networkQueryId3, networkQueryId2)) } @Test def testDeleteQuery = afterCreatingTables { //A RunQueryResponse with all types of QueryResults: count, breakdown, and error val response = countRunQueryResponse.withResults(Seq(countQueryResult, breakdownQueryResult1, breakdownQueryResult2, errorQueryResult1, errorQueryResult2)) doTestFindResultsFor(response) { resultIdsByType => insertCount(resultIdsByType) insertErrors(resultIdsByType) insertBreakdowns(resultIdsByType, breakdownsByType) } { (resultIdsByType, resultOption) => val Some(result) = resultOption validateCount(resultIdsByType, result) validateBreakdowns(result) validateErrors(result) } dao.deleteQuery(networkQueryId1) dao.findQueryByNetworkId(networkQueryId1) should be(None) } @Test def testRenameQuery = afterCreatingTables { dao.insertQuery(masterId1, networkQueryId1, authn, queryDef1, isFlagged = false, hasBeenRun = true, flagMessage = None) { val Some(query) = dao.findQueryByNetworkId(networkQueryId1) query.name should equal(queryDef1.name) } val newName = "zuh" dao.renameQuery(networkQueryId1, newName) val Some(renamedQuery) = dao.findQueryByNetworkId(networkQueryId1) renamedQuery.name should equal(newName) renamedQuery.id should be(1) renamedQuery.networkId should equal(networkQueryId1) renamedQuery.username should equal(authn.username) renamedQuery.domain should equal(authn.domain) renamedQuery.dateCreated should not be (null) renamedQuery.queryDefinition.name should not equal(queryDef1.name) renamedQuery.queryDefinition.expr should equal(queryDef1.expr) renamedQuery.queryDefinition.timing should equal(queryDef1.timing) renamedQuery.queryDefinition.id should equal(queryDef1.id) renamedQuery.queryDefinition.queryType should equal(queryDef1.queryType) renamedQuery.queryDefinition.constraints should equal(queryDef1.constraints) renamedQuery.queryDefinition.subQueries should equal(queryDef1.subQueries) renamedQuery.isFlagged should be(false) renamedQuery.queryDefinition should not equal(queryDef1) } @Test def testFlagQuery = afterCreatingTables { dao.insertQuery(masterId1, networkQueryId1, authn, queryDef1, isFlagged = false, hasBeenRun = true, flagMessage = None) { val Some(query) = dao.findQueryByNetworkId(networkQueryId1) query.isFlagged should be(false) } dao.flagQuery(networkQueryId1, None) { val Some(flaggedQuery) = dao.findQueryByNetworkId(networkQueryId1) flaggedQuery.isFlagged should be(true) flaggedQuery.flagMessage should be(None) } val message = "askldjjkalshd" dao.flagQuery(networkQueryId1, Some(message)) { val Some(flaggedQuery) = dao.findQueryByNetworkId(networkQueryId1) flaggedQuery.isFlagged should be(true) flaggedQuery.flagMessage should be(Some(message)) } } @Test def testUnFlagQuery = afterCreatingTables { dao.insertQuery(masterId1, networkQueryId1, authn, queryDef1, isFlagged = false, hasBeenRun = true, flagMessage = None) { val Some(query) = dao.findQueryByNetworkId(networkQueryId1) query.isFlagged should be(false) } val message = "askdljasd" dao.flagQuery(networkQueryId1, Some(message)) val Some(flaggedQuery) = dao.findQueryByNetworkId(networkQueryId1) flaggedQuery.isFlagged should be(true) flaggedQuery.flagMessage should be(Some(message)) dao.unFlagQuery(networkQueryId1) val Some(unFlaggedQuery) = dao.findQueryByNetworkId(networkQueryId1) unFlaggedQuery.isFlagged should be(false) unFlaggedQuery.flagMessage should be(None) } @Test def testInsertQueryAndFindQueryByNetworkId = afterCreatingTables { dao.findQueryByNetworkId(networkQueryId1) should be(None) dao.insertQuery(masterId1, networkQueryId1, authn, queryDef1, isFlagged = false, hasBeenRun = true, flagMessage = None) { val Some(ShrineQuery(id, localMasterId, actualNetworkId, name, username, domain, dateCreated, isFlagged, flagMessage,queryDef)) = dao.findQueryByNetworkId(networkQueryId1) id should be(1) localMasterId should equal(masterId1) actualNetworkId should equal(networkQueryId1) name should equal(queryDef.name) username should equal(authn.username) domain should equal(authn.domain) dateCreated should not be (null) //NB: Don't compare, to avoid off-by-a-few errors :/ isFlagged should be(false) queryDef should be(queryDef1) } //Inserting a query with the same values should be allowed, it should just create a new row with a new id dao.insertQuery(masterId1, networkQueryId1, authn, queryDef1, isFlagged = false, hasBeenRun = true, flagMessage = None) { //However, the first shrine_query row with the passed networkQueryId should be returned, not the one we just inserted val Some(ShrineQuery(id, localMasterId, actualNetworkId, name, username, domain, dateCreated, isFlagged, flagMessage,queryDef)) = dao.findQueryByNetworkId(networkQueryId1) id should be(1) localMasterId should equal(masterId1) actualNetworkId should equal(networkQueryId1) username should equal(authn.username) domain should equal(authn.domain) dateCreated should not be (null) //NB: Don't compare, to avoid off-by-a-few errors :/ queryDef should equal(queryDef1) isFlagged should be(false) } } @Test def testFindQueriesByUserAndDomain: Unit = afterCreatingTables { dao.findQueriesByUserAndDomain("", "", 50) should equal(Nil) dao.insertQuery(masterId1, networkQueryId1, authn, queryDef1, isFlagged = false, hasBeenRun = true, flagMessage = None) //Make next query happen 10 milliseconds later, so we can distinguish it from the one we just inserted //(java.sql.Timestamps have 1ms resolution, it appears?) Thread.sleep(10) dao.insertQuery(masterId2, networkQueryId2, authn, queryDef1, isFlagged = false, hasBeenRun = true, flagMessage = None) dao.findQueriesByUserAndDomain("", "", 50) should equal(Nil) val Seq(foundQuery1, foundQuery2) = dao.findQueriesByUserAndDomain(authn.domain, authn.username, 50) foundQuery1.domain should equal(authn.domain) foundQuery1.username should equal(authn.username) foundQuery1.localId should equal(masterId2) foundQuery1.networkId should equal(networkQueryId2) foundQuery1.queryDefinition should equal(queryDef1) foundQuery2.domain should equal(authn.domain) foundQuery2.username should equal(authn.username) foundQuery2.localId should equal(masterId1) foundQuery2.networkId should equal(networkQueryId1) foundQuery2.queryDefinition should equal(queryDef1) val Seq(foundQuery) = dao.findQueriesByUserAndDomain(authn.domain, authn.username, 1) foundQuery should equal(foundQuery1) } @Test def testInsertQuery: Unit = { def doTestInsertQuery(flagged: Boolean, run: Boolean): Unit = afterCreatingTables { val ids = for (i <- 1 to 2) yield dao.insertQuery(masterId1, networkQueryId1, authn, queryDef1, isFlagged = flagged, hasBeenRun = run, flagMessage = None) ids should equal(Seq(1, 2)) def testRow(r: ShrineQuery) { r.localId should equal(masterId1) r.networkId should equal(networkQueryId1) r.dateCreated should not be (null) // :/ r.domain should equal(authn.domain) r.username should equal(authn.username) r.queryDefinition should equal(queryDef1) r.isFlagged should equal(flagged) } val rows = list(queryRows) val Seq(row1, row2) = rows row1.id should be(1) row2.id should be(2) rows.foreach(testRow) } doTestInsertQuery(true, true) doTestInsertQuery(true, false) doTestInsertQuery(false, true) doTestInsertQuery(false, false) } @Test def testInsertQueryResultsOnlyCount = afterCreatingTables { intercept[Exception] { //Should fail due to foreign key constraint dao.insertQueryResults(-1, countRunQueryResponse.results) } val (resultIdsByType, resultRows) = doInsertQueryResultsTest(countRunQueryResponse) val Seq(resultRow) = resultRows resultRow.resultType should equal(PATIENT_COUNT_XML) resultRow.status should equal(QueryResult.StatusType.Finished) resultIdsByType should equal(Map(PATIENT_COUNT_XML -> Seq(resultRow.id))) } @Test def testInsertQueryResultsOnlyErrors = afterCreatingTables { val (resultIdsByType, resultRows) = doInsertQueryResultsTest(onlyErrorsRunQueryResponse) resultRows.foreach { resultRow => resultRow.elapsed should be(None) resultRow.resultType should equal(ERROR) resultRow.status should equal(QueryResult.StatusType.Error) } } @Test def testInsertQueryResultsNoErrorsOneCountSomeBreakdowns = afterCreatingTables { val (resultIdsByType, resultRows) = doInsertQueryResultsTest(countAndBreakdownsRunQueryResponse) resultIdsByType.keySet should equal(Set(PATIENT_COUNT_XML, PATIENT_AGE_COUNT_XML, PATIENT_GENDER_COUNT_XML)) resultIdsByType.values.forall(_.size == 1) should be(true) val countResultRow = resultRows.filter(_.resultType == PATIENT_COUNT_XML).head countResultRow.resultType should equal(PATIENT_COUNT_XML) resultRows.filter(row => Set(PATIENT_AGE_COUNT_XML, PATIENT_GENDER_COUNT_XML).contains(row.resultType)).size should be(2) resultRows.foreach { resultRow => resultRow.elapsed should not be (None) resultRow.status should equal(QueryResult.StatusType.Finished) } } private def doInsertQueryResultsTest(response: RawCrcRunQueryResponse): (Map[ResultOutputType, Seq[Int]], Seq[QueryResultRow]) = { list(queryResultRows).isEmpty should be(true) val queryId = dao.insertQuery(masterId1, networkQueryId1, authn, queryDef1, isFlagged = false, hasBeenRun = true, flagMessage = None) val resultIdsByType = dao.insertQueryResults(queryId, response.results) val resultRows = list(queryResultRows) resultRows.foreach { resultRow => resultRow.elapsed should not be (null) resultRow.lastUpdated should not be (null) resultRow.queryId should equal(queryId) } list(errorResultRows).isEmpty should be(true) list(countResultRows).isEmpty should be(true) list(breakdownResultRows).isEmpty should be(true) (resultIdsByType, resultRows) } @Test def testInsertCountResult = afterCreatingTables { val queryId = dao.insertQuery(masterId1, networkQueryId1, authn, queryDef1, isFlagged = false, hasBeenRun = true, flagMessage = None) val response = RawCrcRunQueryResponse(networkQueryId1, now.get, authn.username, authn.domain, queryDef1, instanceId, toQueryResultMap(Seq(countQueryResult))) val resultIdsByType = dao.insertQueryResults(queryId, response.results) val Seq(resultRow) = list(queryResultRows) list(countResultRows).isEmpty should be(true) dao.insertCountResult(resultRow.id, countQueryResult.setSize, countQueryResult.setSize + 2) val Seq(countResultRow) = list(countResultRows) countResultRow.creationDate should not be (null) countResultRow.obfuscatedValue should equal(countQueryResult.setSize + 2) countResultRow.originalValue should equal(countQueryResult.setSize) countResultRow.resultId should equal(resultRow.id) intercept[Exception] { //Should fail due to foreign key constraint dao.insertCountResult(-12345, countQueryResult.setSize, countQueryResult.setSize + 2) } } @Test def testInsertBreakdownResults = afterCreatingTables { val (resultIdsByType, resultRows) = doInsertQueryResultsTest(onlyBreakdownsRunQueryResponse) resultIdsByType.keySet should equal(Set(PATIENT_AGE_COUNT_XML, PATIENT_GENDER_COUNT_XML)) resultIdsByType.values.forall(_.size == 1) should be(true) val Seq(breakdownResultRow1, breakdownResultRow2) = resultRows dao.insertBreakdownResults(resultIdsByType, breakdownsByType, breakdownsByType.mapValues(_.mapValues(_ + 1))) val ageBreakdownRows = list(breakdownResultRows).filter(_.resultId == resultIdsByType(PATIENT_AGE_COUNT_XML).head) val genderBreakdownRows = list(breakdownResultRows).filter(_.resultId == resultIdsByType(PATIENT_GENDER_COUNT_XML).head) { val ageRowsByName = ageBreakdownRows.map(row => (row.dataKey, row)).toMap ageRowsByName("x").originalValue should equal(1) ageRowsByName("y").originalValue should equal(2) ageRowsByName("x").obfuscatedValue should equal(2) ageRowsByName("y").obfuscatedValue should equal(3) } { val genderRowsByName = genderBreakdownRows.map(row => (row.dataKey, row)).toMap genderRowsByName("a").originalValue should equal(123) genderRowsByName("b").originalValue should equal(456) genderRowsByName("a").obfuscatedValue should equal(124) genderRowsByName("b").obfuscatedValue should equal(457) } intercept[Exception] { //Should fail due to foreign key constraint dao.insertBreakdownResults(Map(PATIENT_AGE_COUNT_XML -> Seq(-1000)), breakdownsByType, breakdownsByType) } } @Test def testInsertErrorResult = afterCreatingTables { val queryId = dao.insertQuery(masterId1, networkQueryId1, authn, queryDef1, isFlagged = false, hasBeenRun = true, flagMessage = None) val response = countRunQueryResponse.withResults(Seq(errorQueryResult1)) val resultIdsByType = dao.insertQueryResults(queryId, response.results) val Seq(resultRow) = list(queryResultRows) list(errorResultRows).isEmpty should be(true) - val pd = TestProblem.toDigest + val pd = TestProblem().toDigest dao.insertErrorResult(resultRow.id, message1,pd.codec,pd.stampText,pd.summary,pd.description,pd.detailsXml) val Seq(errorResultRow) = list(errorResultRows) errorResultRow.message should equal(message1) errorResultRow.resultId should equal(resultRow.id) intercept[Exception] { //Should fail due to foreign key constraint dao.insertErrorResult(-12345, "",pd.codec,pd.stampText,pd.summary,pd.description,pd.detailsXml) } } @Test def testFindResultsFor = afterCreatingTables { //A RunQueryResponse with all types of QueryResults: count, breakdown, and error val response = countRunQueryResponse.withResults(Seq(countQueryResult, breakdownQueryResult1, breakdownQueryResult2, errorQueryResult1, errorQueryResult2)) doTestFindResultsFor(response) { resultIdsByType => insertCount(resultIdsByType) insertErrors(resultIdsByType) insertBreakdowns(resultIdsByType, breakdownsByType) } { case (resultIdsByType, resultOption) => val Some(result) = resultOption validateCount(resultIdsByType, result) validateBreakdowns(result) validateErrors(result) } } @Test def testFindResultsForOnlyCount = afterCreatingTables { //A RunQueryResponse with only a count QueryResult val response = countRunQueryResponse doTestFindResultsFor(response) { resultIdsByType => insertCount(resultIdsByType) } { (resultIdsByType, resultOption) => val Some(result) = resultOption validateCount(resultIdsByType, result) result.breakdowns.isEmpty should be(true) result.errors.isEmpty should be(true) } } @Test def testFindResultsForOnlyErrors = afterCreatingTables { //A RunQueryResponse with only errors val response = onlyErrorsRunQueryResponse doTestFindResultsFor(response) { resultIdsByType => insertErrors(resultIdsByType) } { (resultIdsByType, resultOption) => resultOption should be(None) } } @Test def testFindResultsForOnlyBreakdowns = afterCreatingTables { //A RunQueryResponse with only breakdowns val response = countRunQueryResponse.withResults(Seq(countQueryResult, breakdownQueryResult1, breakdownQueryResult2, errorQueryResult1, errorQueryResult2)) doTestFindResultsFor(response) { resultIdsByType => insertBreakdowns(resultIdsByType, breakdownsByType) } { (resultIdsByType, resultOption) => resultOption should be(None) } } private def insertCount(resultIdsByType: Map[ResultOutputType, Seq[Int]]) { dao.insertCountResult(resultIdsByType(PATIENT_COUNT_XML).head, count, count + 42) } private def insertErrors(resultIdsByType: Map[ResultOutputType, Seq[Int]]) { (resultIdsByType(ERROR) zip Seq(message1, message2)).foreach { case (resultId, message) => - val pd = TestProblem.toDigest + val pd = TestProblem().toDigest dao.insertErrorResult(resultId, message,pd.codec,pd.stampText,pd.summary,pd.description,pd.detailsXml) } } private def insertBreakdowns(resultIdsByType: Map[ResultOutputType, Seq[Int]], breakdownsByType: Map[ResultOutputType, I2b2ResultEnvelope]) { dao.insertBreakdownResults(resultIdsByType, breakdownsByType, breakdownsByType.mapValues(_.mapValues(_ + 42))) } private def validateCount(resultIdsByType: Map[ResultOutputType, Seq[Int]], result: ShrineQueryResult) { val foundCount = result.count foundCount.resultId should equal(resultIdsByType(PATIENT_COUNT_XML).head) foundCount.data.get.originalValue should equal(count) foundCount.data.get.obfuscatedValue should equal(count + 42) foundCount.creationDate should not be (null) } private def validateBreakdowns(result: ShrineQueryResult) { val retrievedBreakdownsByType = result.breakdowns.groupBy(_.resultType).mapValues(_.head) retrievedBreakdownsByType(PATIENT_AGE_COUNT_XML).resultType should equal(PATIENT_AGE_COUNT_XML) retrievedBreakdownsByType(PATIENT_AGE_COUNT_XML).data should equal(Map("x" -> ObfuscatedPair(1, 43), "y" -> ObfuscatedPair(2, 44))) retrievedBreakdownsByType(PATIENT_GENDER_COUNT_XML).resultType should equal(PATIENT_GENDER_COUNT_XML) retrievedBreakdownsByType(PATIENT_GENDER_COUNT_XML).data should equal(Map("a" -> ObfuscatedPair(123, 165), "b" -> ObfuscatedPair(456, 498))) } private def validateErrors(result: ShrineQueryResult) { val Seq(err1, err2) = result.errors err1.message should equal(message1) err2.message should equal(message2) } private def doTestFindResultsFor(response: RawCrcRunQueryResponse)(inserts: Map[ResultOutputType, Seq[Int]] => Any)(validate: (Map[ResultOutputType, Seq[Int]], Option[ShrineQueryResult]) => Any) = { dao.findResultsFor(networkQueryId1) should be(None) val queryId = dao.insertQuery(masterId1, networkQueryId1, authn, queryDef1, isFlagged = false, hasBeenRun = true, flagMessage = None) val resultIdsByType = dao.insertQueryResults(queryId, response.results) inserts(resultIdsByType) val resultOption = dao.findResultsFor(networkQueryId1) validate(resultIdsByType, resultOption) } } \ No newline at end of file diff --git a/adapter/adapter-service/src/test/scala/net/shrine/adapter/service/AbstractI2b2AdminResourceJaxrsTest.scala b/adapter/adapter-service/src/test/scala/net/shrine/adapter/service/AbstractI2b2AdminResourceJaxrsTest.scala index 8d65f28d7..0e49be7ee 100644 --- a/adapter/adapter-service/src/test/scala/net/shrine/adapter/service/AbstractI2b2AdminResourceJaxrsTest.scala +++ b/adapter/adapter-service/src/test/scala/net/shrine/adapter/service/AbstractI2b2AdminResourceJaxrsTest.scala @@ -1,101 +1,102 @@ package net.shrine.adapter.service import junit.framework.TestCase import net.shrine.adapter.AdapterTestHelpers import net.shrine.adapter.dao.squeryl.AbstractSquerylAdapterTest import net.shrine.client.{HttpClient, HttpResponse, JerseyHttpClient} import net.shrine.crypto.TrustParam.AcceptAllCerts +import net.shrine.problem.{TestProblem, ProblemSources, AbstractProblem} import net.shrine.protocol.{DefaultBreakdownResultOutputTypes, ErrorResponse, I2b2AdminReadQueryDefinitionRequest, I2b2AdminRequestHandler, QueryMaster, ReadI2b2AdminPreviousQueriesRequest, ReadPreviousQueriesResponse, ReadQueryDefinitionResponse} import net.shrine.protocol.query.QueryDefinition import net.shrine.util.{ShouldMatchersForJUnit, XmlUtil} import org.junit.{After, Before} import scala.xml.XML /** * @author clint * @since Apr 24, 2013 */ abstract class AbstractI2b2AdminResourceJaxrsTest extends TestCase with JerseyTestComponent[I2b2AdminRequestHandler] with AbstractSquerylAdapterTest with ShouldMatchersForJUnit with CanLoadTestData with AdapterTestHelpers { import scala.concurrent.duration._ protected def adminClient = I2b2AdminClient(resourceUrl, JerseyHttpClient(AcceptAllCerts, 5.minutes)) override def resourceClass(handler: I2b2AdminRequestHandler) = I2b2AdminResource(handler, DefaultBreakdownResultOutputTypes.toSet) override val basePath = "i2b2/admin/request" @Before override def setUp(): Unit = this.JerseyTest.setUp() @After override def tearDown(): Unit = this.JerseyTest.tearDown() - + protected object NeverAuthenticatesMockPmHttpClient extends HttpClient { - override def post(input: String, url: String): HttpResponse = HttpResponse.ok(ErrorResponse("blarg").toI2b2String) + override def post(input: String, url: String): HttpResponse = HttpResponse.ok(ErrorResponse(TestProblem(summary = "blarg")).toI2b2String) } protected object AlwaysAuthenticatesMockPmHttpClient extends HttpClient { override def post(input: String, url: String): HttpResponse = { HttpResponse.ok(XmlUtil.stripWhitespace { Some user { userId } { domain } { password } MANAGER }.toString) } } protected def doTestReadQueryDefinition(networkQueryId: Long, expectedQueryNameAndQueryDef: Option[(String, QueryDefinition)]) { val request = I2b2AdminReadQueryDefinitionRequest(projectId, waitTime, authn, networkQueryId) val resp = adminClient.readQueryDefinition(request) def stripNamespaces(s: String) = XmlUtil.stripNamespaces(XML.loadString(s)) expectedQueryNameAndQueryDef match { case Some((expectedQueryName, expectedQueryDef)) => { val response @ ReadQueryDefinitionResponse(masterId, name, userId, createDate, queryDefinition) = resp masterId should be(networkQueryId) name should be(expectedQueryName) userId should be(authn.username) createDate should not be (null) //NB: I'm not sure why whacky namespaces were coming back from the resource; //this checks that the gist of the queryDef XML makes it back. //TODO: revisit this stripNamespaces(queryDefinition) should equal(stripNamespaces(expectedQueryDef.toI2b2String)) } case None => resp.isInstanceOf[ErrorResponse] should be(true) } } protected def doTestReadI2b2AdminPreviousQueries(request: ReadI2b2AdminPreviousQueriesRequest, expectedQueryMasters: Seq[QueryMaster]) { val ReadPreviousQueriesResponse(queryMasters) = adminClient.readI2b2AdminPreviousQueries(request) if(expectedQueryMasters.isEmpty) { queryMasters.isEmpty should be(true) } else { (queryMasters zip expectedQueryMasters).foreach { case (queryMaster, expected) => queryMaster.createDate should not be(null) queryMaster.name should equal(expected.name) queryMaster.queryMasterId should equal(expected.queryMasterId) queryMaster.userId should equal(expected.userId) queryMaster.groupId should equal(expected.groupId) queryMaster.flagged should equal(expected.flagged) } } } } \ No newline at end of file diff --git a/adapter/adapter-service/src/test/scala/net/shrine/adapter/service/I2b2AdminResourceJaxrsTest.scala b/adapter/adapter-service/src/test/scala/net/shrine/adapter/service/I2b2AdminResourceJaxrsTest.scala index c58f32baa..9715b3912 100644 --- a/adapter/adapter-service/src/test/scala/net/shrine/adapter/service/I2b2AdminResourceJaxrsTest.scala +++ b/adapter/adapter-service/src/test/scala/net/shrine/adapter/service/I2b2AdminResourceJaxrsTest.scala @@ -1,194 +1,194 @@ package net.shrine.adapter.service import com.sun.jersey.test.framework.{AppDescriptor, JerseyTest} import net.shrine.adapter.service.I2b2AdminResourceJaxrsTest._ import net.shrine.client.JerseyHttpClient import net.shrine.crypto.TrustParam.AcceptAllCerts import net.shrine.problem.TestProblem import net.shrine.protocol.{AbstractReadQueryDefinitionRequest, AuthenticationInfo, Credential, DefaultBreakdownResultOutputTypes, I2b2AdminReadQueryDefinitionRequest, I2b2AdminRequestHandler, I2b2AdminUserWithRole, QueryMaster, QueryResult, ReadI2b2AdminPreviousQueriesRequest, ReadI2b2AdminQueryingUsersRequest, ReadI2b2AdminQueryingUsersResponse, ReadPreviousQueriesResponse, ReadQueryDefinitionResponse, RunHeldQueryRequest, RunQueryResponse, ShrineResponse} import net.shrine.protocol.query.{QueryDefinition, Term} import net.shrine.util.{JerseyAppDescriptor, ShouldMatchersForJUnit, XmlDateHelper, XmlUtil} import org.junit.{After, Before, Test} import scala.xml.XML /** * @author clint * @since Apr 10, 2013 */ //noinspection ScalaUnnecessaryParentheses final class I2b2AdminResourceJaxrsTest extends JerseyTest with ShouldMatchersForJUnit { var handler: MockShrineRequestHandler = _ def resourceUrl = resource.getURI.toString + "i2b2/admin/request" override def configure: AppDescriptor = { JerseyAppDescriptor.thatCreates((h: I2b2AdminRequestHandler) => I2b2AdminResource(h, DefaultBreakdownResultOutputTypes.toSet)).using { handler = new MockShrineRequestHandler handler } } @Before override def setUp(): Unit = super.setUp() @After override def tearDown(): Unit = super.tearDown() import scala.concurrent.duration._ def adminClient = I2b2AdminClient(resourceUrl, new JerseyHttpClient(AcceptAllCerts, 5.minutes)) @Test def testReadQueryDefinition() { val queryId = 987654321L val request = I2b2AdminReadQueryDefinitionRequest(projectId, waitTime, authn, queryId) val currentHandler = handler val response = adminClient.readQueryDefinition(request).asInstanceOf[ReadQueryDefinitionResponse] response should not be(null) response.masterId should equal(queryId) response.name should equal("some-query-name") response.createDate should not be(null) response.userId should equal(authn.username) def stripNamespaces(s: String) = XmlUtil.stripNamespaces(XML.loadString(s)) //NB: I'm not sure why whacky namespaces were coming back from the resource; //this checks that the gist of the queryDef XML makes it back. //TODO: revisit this stripNamespaces(response.queryDefinition) should equal(stripNamespaces(queryDef.toI2b2String)) currentHandler.shouldBroadcastParam should be(false) currentHandler.readI2b2AdminPreviousQueriesParam should be(null) currentHandler.readQueryDefinitionParam should equal(request) } @Test def testReadI2b2AdminPreviousQueries() { val searchString = "asdk;laskd;lask;gdjsg" val maxResults = 123 val sortOrder = ReadI2b2AdminPreviousQueriesRequest.SortOrder.Ascending val categoryToSearchWithin = ReadI2b2AdminPreviousQueriesRequest.Category.All val searchStrategy = ReadI2b2AdminPreviousQueriesRequest.Strategy.Exact import ReadI2b2AdminPreviousQueriesRequest.Username._ val request = ReadI2b2AdminPreviousQueriesRequest(projectId, waitTime, authn, Exactly("@"), searchString, maxResults, None, sortOrder, searchStrategy, categoryToSearchWithin) val currentHandler = handler val response = adminClient.readI2b2AdminPreviousQueries(request).asInstanceOf[ReadPreviousQueriesResponse] response should not be(null) response.queryMasters should equal(Seq(queryMaster)) currentHandler.shouldBroadcastParam should be(false) currentHandler.readI2b2AdminPreviousQueriesParam should be(request) currentHandler.readQueryDefinitionParam should be(null) } @Test def testReadI2b2QueryingUsers() { val projectIdToSearchFor = "foo-project-id" val request = ReadI2b2AdminQueryingUsersRequest(projectId, waitTime, authn, projectIdToSearchFor) val currentHandler = handler val response = adminClient.readI2b2AdminQueryingUsers(request).asInstanceOf[ReadI2b2AdminQueryingUsersResponse] response should not be(null) response.users should equal(users) currentHandler.shouldBroadcastParam should be(false) currentHandler.readI2b2AdminPreviousQueriesParam should be(null) currentHandler.readI2b2AdminQueryingUsersParam should be(request) currentHandler.readQueryDefinitionParam should be(null) } } object I2b2AdminResourceJaxrsTest { private val queryDef = QueryDefinition("foo", Term("x")) private val userId = "some-user-id" private val domain = "some-domain" private lazy val authn = new AuthenticationInfo(domain, userId, new Credential("some-val", false)) private val projectId = "some-project-id" import scala.concurrent.duration._ private val waitTime = 12345.milliseconds private lazy val queryMaster = QueryMaster( queryMasterId = "queryMasterId", networkQueryId = 123456789L, name = "name", userId = userId, groupId = domain, createDate = XmlDateHelper.now, flagged = Some(true)) private lazy val users = Seq( I2b2AdminUserWithRole("projectId1", "joe user", "some important role"), I2b2AdminUserWithRole("projectId2", "jane user", "some other important role"), I2b2AdminUserWithRole("projectId3", "some user", "some super important role")) /** * Mock ShrineRequestHandler; stores passed parameters for later inspection. * Private, since this is (basically) the enclosing test class's state */ final class MockShrineRequestHandler extends I2b2AdminRequestHandler { private val lock = new AnyRef def shouldBroadcastParam = lock.synchronized(_shouldBroadcastParam) def readQueryDefinitionParam = lock.synchronized(_readQueryDefinitionParam) def readI2b2AdminPreviousQueriesParam = lock.synchronized(_readI2b2AdminPreviousQueriesParam) def readI2b2AdminQueryingUsersParam = lock.synchronized(_readI2b2AdminQueryingUsersParam) def runHeldQueryParam = lock.synchronized(_runHeldQueryParam) private var _shouldBroadcastParam = false private var _readQueryDefinitionParam: AbstractReadQueryDefinitionRequest = _ private var _readI2b2AdminPreviousQueriesParam: ReadI2b2AdminPreviousQueriesRequest = _ private var _readI2b2AdminQueryingUsersParam: ReadI2b2AdminQueryingUsersRequest = _ private var _runHeldQueryParam: RunHeldQueryRequest = _ override def readI2b2AdminPreviousQueries(request: ReadI2b2AdminPreviousQueriesRequest, shouldBroadcast: Boolean): ShrineResponse = setShouldBroadcastAndThen(shouldBroadcast) { lock.synchronized { _readI2b2AdminPreviousQueriesParam = request } ReadPreviousQueriesResponse(Seq(queryMaster)) } override def readI2b2AdminQueryingUsers(request: ReadI2b2AdminQueryingUsersRequest, shouldBroadcast: Boolean): ShrineResponse = setShouldBroadcastAndThen(shouldBroadcast) { lock.synchronized { _readI2b2AdminQueryingUsersParam = request } ReadI2b2AdminQueryingUsersResponse(users) } override def readQueryDefinition(request: I2b2AdminReadQueryDefinitionRequest, shouldBroadcast: Boolean): ShrineResponse = setShouldBroadcastAndThen(shouldBroadcast) { lock.synchronized { _readQueryDefinitionParam = request } ReadQueryDefinitionResponse(request.queryId, "some-query-name", request.authn.username, XmlDateHelper.now, queryDef.toI2b2String) } override def runHeldQuery(request: RunHeldQueryRequest, shouldBroadcast: Boolean): ShrineResponse = { lock.synchronized { _runHeldQueryParam = request } - RunQueryResponse(request.networkQueryId, XmlDateHelper.now, request.authn.username, request.projectId, QueryDefinition("bogus", Term("placeholder")), 12345L, QueryResult.errorResult(Some("foo"), "not actually an error",TestProblem)) + RunQueryResponse(request.networkQueryId, XmlDateHelper.now, request.authn.username, request.projectId, QueryDefinition("bogus", Term("placeholder")), 12345L, QueryResult.errorResult(Some("foo"), "not actually an error",TestProblem())) } private def setShouldBroadcastAndThen(shouldBroadcast: Boolean)(f: => ShrineResponse): ShrineResponse = { try { f } finally { lock.synchronized { _shouldBroadcastParam = shouldBroadcast } } } } } \ No newline at end of file diff --git a/commons/protocol/src/main/scala/net/shrine/protocol/ErrorResponse.scala b/commons/protocol/src/main/scala/net/shrine/protocol/ErrorResponse.scala index 57fe1c3e7..904ea7093 100644 --- a/commons/protocol/src/main/scala/net/shrine/protocol/ErrorResponse.scala +++ b/commons/protocol/src/main/scala/net/shrine/protocol/ErrorResponse.scala @@ -1,125 +1,116 @@ package net.shrine.protocol import net.shrine.log.Loggable -import net.shrine.problem.{ProblemNotYetEncoded, LoggingProblemHandler, Problem, ProblemDigest} +import net.shrine.problem.{LoggingProblemHandler, Problem, ProblemDigest} import scala.xml.{NodeBuffer, NodeSeq} import net.shrine.util.XmlUtil import net.shrine.serialization.XmlUnmarshaller import net.shrine.serialization.I2b2Unmarshaller import net.shrine.util.NodeSeqEnrichments import scala.util.Try import scala.util.control.NonFatal /** * @author Bill Simons * @since 4/25/11 * @see http://cbmi.med.harvard.edu * @see http://chip.org *

* NOTICE: This software comes with NO guarantees whatsoever and is * licensed as Lgpl Open Source * @see http://www.gnu.org/licenses/lgpl.html * * NB: Now a case class for structural equality */ final case class ErrorResponse(errorMessage: String,problemDigest:ProblemDigest) extends ShrineResponse { override protected def status: NodeSeq = { val buffer = new NodeBuffer buffer += { errorMessage } buffer += problemDigest.toXml } override protected def i2b2MessageBody = null import ErrorResponse.rootTagName override def toXml = { XmlUtil.stripWhitespace { val xml = XmlUtil.renameRootTag(rootTagName) { { errorMessage } {problemDigest.toXml} } xml } } } object ErrorResponse extends XmlUnmarshaller[ErrorResponse] with I2b2Unmarshaller[ErrorResponse] with HasRootTagName with Loggable { val rootTagName = "errorResponse" - //todo deprecate this one - def apply(errorMessage:String,problem:Option[Problem] = None) = { - new ErrorResponse(errorMessage,problem.fold{ - val problem = ProblemNotYetEncoded(s"'$errorMessage'") - LoggingProblemHandler.handleProblem(problem) //todo someday hook up to the proper problem handler hierarchy. - problem.toDigest - }(p => p.toDigest)) - } - def apply(problem:Problem) = { + LoggingProblemHandler.handleProblem(problem) //todo someday hook up to the proper problem handler hierarchy. new ErrorResponse(problem.summary,problem.toDigest) } - override def fromXml(xml: NodeSeq): ErrorResponse = { val messageXml = xml \ "message" //NB: Fail fast require(messageXml.nonEmpty) val problemDigest = ProblemDigest.fromXml(xml) ErrorResponse(XmlUtil.trim(messageXml),problemDigest) } override def fromI2b2(xml: NodeSeq): ErrorResponse = { import NodeSeqEnrichments.Strictness._ //todo what determines parseFormatA vs parseFormatB when written? It looks like our ErrorResponses use A. def parseFormatA: Try[ErrorResponse] = { for { statusXml <- xml withChild "response_header" withChild "result_status" withChild "status" resultStatusXml <- xml withChild "response_header" withChild "result_status" typeText <- statusXml attribute "type" if typeText == "ERROR" //NB: Fail fast{ statusMessage = XmlUtil.trim(statusXml) problemDigest = ProblemDigest.fromXml(resultStatusXml) } yield { ErrorResponse(statusMessage,problemDigest) } } def parseFormatB: Try[ErrorResponse] = { for { conditionXml <- xml withChild "message_body" withChild "response" withChild "status" withChild "condition" typeText <- conditionXml attribute "type" if typeText == "ERROR" statusMessage = XmlUtil.trim(conditionXml) problemDigest = ErrorStatusFromCrc(Option(statusMessage),xml.text).toDigest//here's another place where an ERROR can have no ProblemDigest } yield { ErrorResponse(statusMessage,problemDigest) } } parseFormatA.recoverWith { case NonFatal(e) => { warn(s"Encountered a problem while parsing an error from I2B2 with 'format A', trying 'format B' ${xml.text}",e) parseFormatB } }.get } /** * * * * * * Query result instance id 3126 not found * * * * */ } \ No newline at end of file diff --git a/commons/protocol/src/test/scala/net/shrine/protocol/AggregatedRunQueryResponseTest.scala b/commons/protocol/src/test/scala/net/shrine/protocol/AggregatedRunQueryResponseTest.scala index 0abbe99ed..574d82c51 100644 --- a/commons/protocol/src/test/scala/net/shrine/protocol/AggregatedRunQueryResponseTest.scala +++ b/commons/protocol/src/test/scala/net/shrine/protocol/AggregatedRunQueryResponseTest.scala @@ -1,318 +1,318 @@ package net.shrine.protocol import net.shrine.problem.TestProblem import scala.xml.NodeSeq import org.junit.Test import net.shrine.protocol.query.QueryDefinition import net.shrine.protocol.query.Term import net.shrine.util.XmlDateHelper import net.shrine.util.XmlUtil /** * * * @author Justin Quan * @see http://chip.org * @since 8/12/11 */ //noinspection EmptyParenMethodOverridenAsParameterless,EmptyParenMethodAccessedAsParameterless,UnitMethodIsParameterless final class AggregatedRunQueryResponseTest extends ShrineResponseI2b2SerializableValidator { private val queryId = 1L private val queryName = "queryName" private val userId = "user" private val groupId = "group" private val createDate = XmlDateHelper.now private val requestQueryDef = QueryDefinition(queryName, Term("""\\i2b2\i2b2\Demographics\Age\0-9 years old\""")) private val queryInstanceId = 2L private val resultId = 3L private val setSize = 10L private val startDate = createDate private val endDate = createDate private val resultId2 = 4L private val resultType1 = ResultOutputType.PATIENT_COUNT_XML private val resultType2 = ResultOutputType.PATIENT_COUNT_XML private val statusType = QueryResult.StatusType.Finished override def messageBody = { DONE { queryId } { queryName } { userId } { groupId } { createDate } { requestQueryDef.toI2b2 } { queryInstanceId } { queryId } { userId } { groupId } 6 COMPLETED COMPLETED { resultId } { queryInstanceId } 4 { resultType1 } CATNUM LA Number of patients { setSize } { startDate } { endDate } { statusType } 3 FINISHED { resultId2 } { queryInstanceId } 4 { resultType2 } CATNUM LA Number of patients { setSize } { startDate } { endDate } { statusType } 3 FINISHED } private val qr1 = QueryResult( resultId = resultId, instanceId = queryInstanceId, resultType = Option(resultType1), setSize = setSize, startDate = Option(createDate), endDate = Option(createDate), description = None, statusType = statusType, statusMessage = Some(statusType.name), problemDigest = None, breakdowns = Map.empty) private val qr2 = QueryResult( resultId = resultId2, instanceId = queryInstanceId, resultType = Option(resultType2), setSize = setSize, startDate = Option(createDate), endDate = Option(createDate), description = None, statusType = statusType, statusMessage = Some(statusType.name), problemDigest = None, breakdowns = Map.empty) private val runQueryResponse = XmlUtil.stripWhitespace { { queryId } { queryInstanceId } { userId } { groupId } { requestQueryDef.toXml } { createDate } { Seq(qr1, qr2).map(_.toXml) } } import DefaultBreakdownResultOutputTypes.{ values => breakdownTypes } @Test def testFromXml { val actual = AggregatedRunQueryResponse.fromXml(breakdownTypes.toSet)(runQueryResponse).get actual.queryId should equal(queryId) actual.createDate should equal(createDate) actual.userId should equal(userId) actual.groupId should equal(groupId) actual.requestXml should equal(requestQueryDef) actual.queryInstanceId should equal(queryInstanceId) actual.results should equal(Seq(qr1, qr2)) actual.queryName should equal(queryName) } @Test def testToXml { AggregatedRunQueryResponse(queryId, createDate, userId, groupId, requestQueryDef, queryInstanceId, Seq(qr1, qr2)).toXmlString should equal(runQueryResponse.toString) } @Test def testFromI2b2 { val translatedResponse = AggregatedRunQueryResponse.fromI2b2(breakdownTypes.toSet)(response).get translatedResponse.queryId should equal(queryId) translatedResponse.createDate should equal(createDate) translatedResponse.userId should equal(userId) translatedResponse.groupId should equal(groupId) translatedResponse.requestXml should equal(requestQueryDef) translatedResponse.queryInstanceId should equal(queryInstanceId) translatedResponse.results should equal(Seq(qr1, qr2)) translatedResponse.queryName should equal(queryName) } @Test def testFromI2b2StringRequestXml { val hackToProduceXml = new HasResponse { //Produces a message body where the tag contains escaped XML as a String, as is produced by the CRC override def messageBody: NodeSeq = { DONE { queryId } { queryName } { userId } { groupId } { createDate } { requestQueryDef.toI2b2String } { queryInstanceId } { queryId } { userId } { groupId } 6 COMPLETED COMPLETED { resultId } { queryInstanceId } { resultType1 } 1 LIST LA Patient list { setSize } { startDate } { endDate } { statusType } 3 FINISHED { resultId2 } { queryInstanceId } { resultType2 } 4 CATNUM LA Number of patients { setSize } { startDate } { endDate } { statusType } 3 FINISHED } } doTestFromI2b2(hackToProduceXml.response, requestQueryDef) } private def doTestFromI2b2(i2b2Response: NodeSeq, expectedQueryDef: AnyRef) { val translatedResponse = AggregatedRunQueryResponse.fromI2b2(breakdownTypes.toSet)(i2b2Response).get translatedResponse.queryId should equal(queryId) translatedResponse.createDate should equal(createDate) translatedResponse.userId should equal(userId) translatedResponse.groupId should equal(groupId) translatedResponse.requestXml should equal(expectedQueryDef) translatedResponse.queryInstanceId should equal(queryInstanceId) translatedResponse.results should equal(Seq(qr1, qr2)) translatedResponse.queryName should equal(queryName) } @Test def testResultsPartitioned { val actual = AggregatedRunQueryResponse.fromXml(breakdownTypes.toSet)(runQueryResponse).get { val (nonErrors, errors) = actual.resultsPartitioned nonErrors should equal(Seq(qr1, qr2)) errors.size should equal(0) } - def error = QueryResult.errorResult(None, "something broke", TestProblem) + def error = QueryResult.errorResult(None, "something broke", TestProblem()) { val withOnlyErrors = actual.withResults(Seq(error, error)) val (nonErrors, errors) = withOnlyErrors.resultsPartitioned nonErrors.size should equal(0) errors should equal(Seq(error, error)) } { val withErrorsAndSuccesses = actual.withResults(actual.results ++ Seq(error, error)) val (nonErrors, errors) = withErrorsAndSuccesses.resultsPartitioned nonErrors should equal(Seq(qr1, qr2)) errors should equal(Seq(error, error)) } { val withNoResults = actual.withResults(Nil) val (nonErrors, errors) = withNoResults.resultsPartitioned nonErrors.size should equal(0) errors.size should equal(0) } } @Test def testToI2b2 { AggregatedRunQueryResponse(queryId, createDate, userId, groupId, requestQueryDef, queryInstanceId, Seq(qr1, qr2)).toI2b2String should equal(response.toString) } } \ No newline at end of file diff --git a/commons/protocol/src/test/scala/net/shrine/protocol/ErrorResponseTest.scala b/commons/protocol/src/test/scala/net/shrine/protocol/ErrorResponseTest.scala index bbfb0888c..f8065600d 100644 --- a/commons/protocol/src/test/scala/net/shrine/protocol/ErrorResponseTest.scala +++ b/commons/protocol/src/test/scala/net/shrine/protocol/ErrorResponseTest.scala @@ -1,157 +1,158 @@ package net.shrine.protocol import junit.framework.TestCase import net.shrine.problem.TestProblem import net.shrine.util.ShouldMatchersForJUnit import org.junit.Test import scala.xml.NodeSeq import net.shrine.util.XmlUtil /** * @author clint * @since Apr 5, 2013 */ final class ErrorResponseTest extends TestCase with ShouldMatchersForJUnit { val message = "foo" + val problem = TestProblem(message) - val resp = ErrorResponse(message,Some(TestProblem)) + val resp = ErrorResponse(problem) val expectedShrineXml = XmlUtil.stripWhitespace { { message } - {TestProblem.toDigest.toXml} + {problem.toDigest.toXml} } val expectedI2b2Xml = XmlUtil.stripWhitespace { 1.1 2.4 SHRINE 1.3-compatible SHRINE 2011-04-08T16:21:12.251-04:00 { message } - {TestProblem.toDigest.toXml} + {problem.toDigest.toXml} } @Test def testToXml() = doTestToXml(expectedShrineXml, _.toXml) @Test def testToI2b2() = doTestToXml(expectedI2b2Xml, _.toI2b2) @Test def testToXmlRoundTrip() = doTestRoundTrip(_.toXml, ErrorResponse.fromXml) @Test def testToI2b2RoundTrip() = doTestRoundTrip(_.toI2b2, ErrorResponse.fromI2b2) @Test def testFromXml() = doTestFromXml(expectedShrineXml, ErrorResponse.fromXml) @Test def testFromI2b2() = doTestFromXml(expectedI2b2Xml, ErrorResponse.fromI2b2) //NB: See https://open.med.harvard.edu/jira/browse/SHRINE-745 @Test def testFromI2b2AlternateFormat() { val altI2b2Xml = XmlUtil.stripWhitespace { 1.1 2.4 edu.harvard.i2b2.crc 1.5 i2b2 Hive i2b2_QueryTool 0.2 i2b2 Hive 1 i2b2 Log information DONE Query result instance id 3126 not found } val resp = ErrorResponse.fromI2b2(altI2b2Xml) resp should not be null resp.errorMessage should equal("Query result instance id 3126 not found") } private def doTestFromXml(xml: NodeSeq, deserialize: NodeSeq => ErrorResponse) { intercept[Exception] { deserialize(null) } intercept[Exception] { deserialize() } intercept[Exception] { //Correct I2b2 XML structure, wrong status type deserialize({ message }) } val deserialized = deserialize(xml) deserialized.problemDigest.detailsXml should equal(resp.problemDigest.detailsXml) deserialized.problemDigest should equal(resp.problemDigest) deserialized should equal(resp) } private def doTestToXml(expected: NodeSeq, serialize: ErrorResponse => NodeSeq) { val xml = serialize(resp) xml.toString should equal(expected.toString()) } private def doTestRoundTrip(serialize: ErrorResponse => NodeSeq, deserialize: NodeSeq => ErrorResponse) { val unmarshalled = deserialize(serialize(resp)) unmarshalled should equal(resp) } } \ No newline at end of file diff --git a/commons/protocol/src/test/scala/net/shrine/protocol/QueryResultTest.scala b/commons/protocol/src/test/scala/net/shrine/protocol/QueryResultTest.scala index 1b91ae976..9d84499cd 100644 --- a/commons/protocol/src/test/scala/net/shrine/protocol/QueryResultTest.scala +++ b/commons/protocol/src/test/scala/net/shrine/protocol/QueryResultTest.scala @@ -1,498 +1,496 @@ package net.shrine.protocol import net.shrine.problem.{TestProblem, ProblemSources, AbstractProblem} import net.shrine.util.ShouldMatchersForJUnit import org.junit.Test import net.shrine.util.XmlUtil import net.shrine.util.XmlDateHelper import net.shrine.util.XmlGcEnrichments -import scala.xml.{XML, NodeSeq} +import scala.xml.NodeSeq /** * @author Bill Simons * @author clint * @since 8/19/11 * @see http://cbmi.med.harvard.edu * @see http://chip.org *

* NOTICE: This software comes with NO guarantees whatsoever and is * licensed as Lgpl Open Source * @see http://www.gnu.org/licenses/lgpl.html */ //noinspection EmptyParenMethodAccessedAsParameterless,NameBooleanParameters final class QueryResultTest extends ShouldMatchersForJUnit with XmlRoundTripper[QueryResult] with I2b2SerializableValidator { private val date = XmlDateHelper.now private val resultId = 1L private val instanceId = 2L private val resultType = ResultOutputType.PATIENT_COUNT_XML private val setSize = 12L private val statusType = QueryResult.StatusType.Finished private val description = "description" private val statusMessage = "lakjdalsjd" private val queryResult = QueryResult(resultId, instanceId, Some(resultType), setSize, Option(date), Option(date), Option(description), statusType, Option(statusType.name)) import DefaultBreakdownResultOutputTypes.{ values => breakdownTypes, _ } private val resultWithBreakDowns = queryResult.copy( statusMessage = Some(statusMessage), breakdowns = Map(PATIENT_AGE_COUNT_XML -> I2b2ResultEnvelope(PATIENT_AGE_COUNT_XML, Map("foo" -> 1L, "bar" -> 2L)), PATIENT_RACE_COUNT_XML -> I2b2ResultEnvelope(PATIENT_RACE_COUNT_XML, Map("nuh" -> 3L, "zuh" -> 4L)), PATIENT_VITALSTATUS_COUNT_XML -> I2b2ResultEnvelope(PATIENT_VITALSTATUS_COUNT_XML, Map("blarg" -> 5L, "glarg" -> 6L)), PATIENT_GENDER_COUNT_XML -> I2b2ResultEnvelope(PATIENT_GENDER_COUNT_XML, Map("huh" -> 7L, "yeah" -> 8)))) private val expectedWhenBreakdownsArePresent = XmlUtil.stripWhitespace { { resultId } { instanceId } { resultType.toXml } { setSize } { date } { date } { description } { statusType } { statusMessage } { PATIENT_AGE_COUNT_XML } bar 2 foo 1 { PATIENT_GENDER_COUNT_XML } huh 7 yeah 8 { PATIENT_RACE_COUNT_XML } nuh 3 zuh 4 { PATIENT_VITALSTATUS_COUNT_XML } blarg 5 glarg 6 }.toString private val expectedI2b2Xml = XmlUtil.stripWhitespace { { resultId } { instanceId } { description } 4 { resultType } CATNUMLANumber of patients { setSize } { date } { date } { statusType } 3FINISHED }.toString private val expectedI2b2XmlWithBreakdowns = XmlUtil.stripWhitespace { { resultId } { instanceId } { description } { resultType.toI2b2 } { setSize } { date } { date } { statusType } 3FINISHED { PATIENT_AGE_COUNT_XML } bar 2 foo 1 { PATIENT_GENDER_COUNT_XML } huh 7 yeah 8 { PATIENT_RACE_COUNT_XML } nuh 3 zuh 4 { PATIENT_VITALSTATUS_COUNT_XML } blarg 5 glarg 6 }.toString private val expectedI2b2ErrorXml = XmlUtil.stripWhitespace { 0 0 { description } 0 ERROR { statusMessage } }.toString //NB: See https://open.med.harvard.edu/jira/browse/SHRINE-745 private val expectedI2b2IncompleteXml = XmlUtil.stripWhitespace { 0 0 { description } 0 INCOMPLETE { statusMessage } }.toString import scala.xml.XML.loadString //NB: See https://open.med.harvard.edu/jira/browse/SHRINE-745 @Test def testParseIncomplete() { val qr = QueryResult.fromI2b2(breakdownTypes.toSet)(loadString(expectedI2b2IncompleteXml)) qr.statusType should be(QueryResult.StatusType.Incomplete) } @Test def testElapsed() { queryResult.copy(startDate = None).elapsed should be(None) queryResult.copy(endDate = None).elapsed should be(None) queryResult.copy(startDate = None, endDate = None).elapsed should be(None) { val now = XmlDateHelper.now queryResult.copy(startDate = Some(now), endDate = Some(now)).elapsed should equal(Some(0L)) } { val start = XmlDateHelper.now val delta = 123L import XmlGcEnrichments._ import scala.concurrent.duration._ val end = start + delta.milliseconds queryResult.copy(startDate = Some(start), endDate = Some(end)).elapsed should equal(Some(delta)) } } @Test def testIsError() { queryResult.isError should be(false) queryResult.copy(statusType = QueryResult.StatusType.Processing).isError should be(false) queryResult.copy(statusType = QueryResult.StatusType.Finished).isError should be(false) queryResult.copy(statusType = QueryResult.StatusType.Queued).isError should be(false) queryResult.copy(statusType = QueryResult.StatusType.Incomplete).isError should be(false) queryResult.copy(statusType = QueryResult.StatusType.Error).isError should be(true) } @Test def testToXml() { val queryResultForShrine = queryResult.copy(statusMessage = Some(statusMessage)) val expectedWhenNoBreakdowns = XmlUtil.stripWhitespace { { resultId } { instanceId } { resultType.toXml } { setSize } { date } { date } { description } { statusType } { statusMessage } }.toString queryResultForShrine.copy(statusMessage = Some(statusMessage)).toXmlString should equal(expectedWhenNoBreakdowns) val expectedWhenNoStartDate = XmlUtil.stripWhitespace { { resultId } { instanceId } { resultType.toXml } { setSize } { date } { description } { statusType } { statusMessage } }.toString queryResultForShrine.copy(startDate = None).toXmlString should equal(expectedWhenNoStartDate) val expectedWhenNoEndDate = XmlUtil.stripWhitespace { { resultId } { instanceId } { resultType.toXml } { setSize } { date } { description } { statusType } { statusMessage } }.toString queryResultForShrine.copy(endDate = None).toXmlString should equal(expectedWhenNoEndDate) val expectedWhenNoDescription = XmlUtil.stripWhitespace { { resultId } { instanceId } { resultType.toXml } { setSize } { date } { date } { statusType } { statusMessage } }.toString queryResultForShrine.copy(description = None).toXmlString should equal(expectedWhenNoDescription) val expectedWhenNoStatusMessage = XmlUtil.stripWhitespace { { resultId } { instanceId } { resultType.toXml } { setSize } { date } { date } { description } { statusType } }.toString queryResult.copy(statusMessage = None).toXmlString should equal(expectedWhenNoStatusMessage) resultWithBreakDowns.toXmlString should equal(expectedWhenBreakdownsArePresent) } @Test def testFromXml() { QueryResult.fromXml(breakdownTypes.toSet)(loadString(expectedWhenBreakdownsArePresent)) should equal(resultWithBreakDowns) } @Test def testShrineRoundTrip() = { QueryResult.fromXml(breakdownTypes.toSet)(resultWithBreakDowns.toXml) should equal(resultWithBreakDowns) } private def compareIgnoringBreakdowns(actual: QueryResult, expected: QueryResult) { //Ignore breakdowns field, since this can't be serialized to i2b2 format as part of a actual.breakdowns should equal(Map.empty) actual.description should equal(expected.description) actual.endDate should equal(expected.endDate) actual.instanceId should equal(expected.instanceId) actual.resultId should equal(expected.resultId) actual.resultType should equal(expected.resultType) actual.setSize should equal(expected.setSize) actual.startDate should equal(expected.startDate) actual.statusMessage should equal(expected.statusMessage) actual.statusType should equal(expected.statusType) } @Test def testI2b2RoundTrip() = { //NB: Needed because i2b2 handles status messages differently. In the error case, statusMessage is //descriptive; otherwise, it's the all-caps name of the status type. This is different from how //Shrine creates and parses statusMessage XML, so we need a new QueryResult here. (Previously, we //could use the same one, since we were ignoring statusMessage and description when unmarshalling //from i2b2 format.) val newStatusMessage = Some(resultWithBreakDowns.statusType.name) val resultWithBreakDownsForI2b2 = resultWithBreakDowns.copy(statusMessage = newStatusMessage) val unmarshalled = QueryResult.fromI2b2(breakdownTypes.toSet)(resultWithBreakDownsForI2b2.toI2b2) compareIgnoringBreakdowns(unmarshalled, resultWithBreakDownsForI2b2) } @Test def testFromI2b2() { compareIgnoringBreakdowns(QueryResult.fromI2b2(breakdownTypes.toSet)(loadString(expectedI2b2Xml)), queryResult) } @Test def testFromI2b2WithErrors() { - val errorResult = QueryResult.errorResult(Some(description), statusMessage,TestProblem) + val errorResult = QueryResult.errorResult(Some(description), statusMessage,TestProblem()) val actual = QueryResult.fromI2b2(breakdownTypes.toSet)(loadString(expectedI2b2ErrorXml)) compareIgnoringBreakdowns(actual, errorResult) } @Test def testToI2b2() { queryResult.toI2b2String should equal(expectedI2b2Xml) } @Test def testToI2b2WithBreakdowns() { resultWithBreakDowns.toI2b2String should equal(expectedI2b2XmlWithBreakdowns) } @Test def testToI2b2AllStatusTypes(): Unit = { def doTest(statusType: QueryResult.StatusType) { val expectedI2b2Xml = XmlUtil.stripWhitespace { { resultId } { instanceId } { description } { resultType.toI2b2 } { setSize } { date } { date } { statusType } { statusType.i2b2Id.get }{ statusType } }.toString val result = queryResult.copy(statusType = statusType) result.toI2b2String should equal(expectedI2b2Xml) } import QueryResult.StatusType //NB: Error is tested by testToI2b2WithErrors() val nonErrorStatuses = StatusType.values.toSet - StatusType.Error for (statusType <- nonErrorStatuses) { doTest(statusType) } } @Test def testToI2b2WithErrors(): Unit = { - QueryResult.errorResult(Some(description), statusMessage, TestProblem).toI2b2String + QueryResult.errorResult(Some(description), statusMessage, TestProblem()).toI2b2String } @Test def testWithErrorsAndProblemDigest():Unit = { - case class TestProblem(override val summary: String = "test summary",override val description:String = "test description") extends AbstractProblem(ProblemSources.Unknown) - val testProblem:TestProblem = new TestProblem() val expected: NodeSeq = 0 0 description 0 ERROR lakjdalsjd {testProblem.problemName} {testProblem.stamp.pretty}

{testProblem.summary} {testProblem.description} {testProblem.detailsXml} val actual = QueryResult.errorResult( Some(description), statusMessage, testProblem) val i2b2Xml: NodeSeq = actual.toI2b2 val pretty = new scala.xml.PrettyPrinter(80, 2) pretty.formatNodes(i2b2Xml) should equal(pretty.formatNodes(expected)) val fromI2b2 = QueryResult.fromI2b2(Set.empty)(i2b2Xml) fromI2b2 should equal(actual) val xml = actual.toXml val fromXml = QueryResult.fromXml(Set.empty)(xml) fromXml should equal(actual) } } \ No newline at end of file diff --git a/commons/protocol/src/test/scala/net/shrine/protocol/ReadPreviousQueriesResponseTest.scala b/commons/protocol/src/test/scala/net/shrine/protocol/ReadPreviousQueriesResponseTest.scala index 0a4256507..44d14217e 100644 --- a/commons/protocol/src/test/scala/net/shrine/protocol/ReadPreviousQueriesResponseTest.scala +++ b/commons/protocol/src/test/scala/net/shrine/protocol/ReadPreviousQueriesResponseTest.scala @@ -1,177 +1,178 @@ package net.shrine.protocol +import net.shrine.problem.TestProblem import org.junit.Test import net.shrine.util.XmlUtil import net.shrine.util.XmlDateHelper import javax.xml.datatype.XMLGregorianCalendar /** * @author Bill Simons * @since 4/12/11 * @see http://cbmi.med.harvard.edu * @see http://chip.org *

* NOTICE: This software comes with NO guarantees whatsoever and is * licensed as Lgpl Open Source * @see http://www.gnu.org/licenses/lgpl.html */ final class ReadPreviousQueriesResponseTest extends ShrineResponseI2b2SerializableValidator { val queryMasterId1 = 1111111L val queryMasterId2 = 222222L val networkQueryId1 = 123455667L val networkQueryId2 = 98327592L val queryName1 = "name1" val queryName2 = "name2" val userId1 = Some("user1") val userId2 = Some("user2") val groupId1 = Some("group1") val groupId2 = Some("group2") val createDate1 = XmlDateHelper.now val createDate2 = XmlDateHelper.now val flagged1 = Some(true) val flagged2 = None val flagMessage1 = Some("askldhlaksdjlkasdjklasdjl") val flagMessage2 = None val queryMaster1 = makeQueryMaster(queryMasterId1, networkQueryId1, queryName1, userId1, groupId1, createDate1, flagged1, flagMessage1) val queryMaster2 = makeQueryMaster(queryMasterId2, networkQueryId2, queryName2, userId2, groupId2, createDate2, flagged2, flagMessage2) def makeQueryMaster(queryMasterId: Long, networkQueryId: Long, queryName: String, userId: Option[String], groupId: Option[String], createDate: XMLGregorianCalendar, flagged: Option[Boolean], flagMessage: Option[String]) = { QueryMaster(String.valueOf(queryMasterId), networkQueryId, queryName, userId.get, groupId.get, createDate, flagged, flagMessage) } def messageBody = XmlUtil.stripWhitespace { DONE { queryMasterId1 } { networkQueryId1 } { queryName1 } { userId1.get } { groupId1.get } { createDate1 } { flagged1.get } { flagMessage1.get } { queryMasterId2 } { networkQueryId2 } { queryName2 } { userId2.get } { groupId2.get } { createDate2 } } //keep the held field around to be sure that old messages can be read. def oldMessageBody = XmlUtil.stripWhitespace { DONE { queryMasterId1 } { networkQueryId1 } { queryName1 } { userId1.get } { groupId1.get } { createDate1 } { flagged1.get } { flagMessage1.get } { queryMasterId2 } { networkQueryId2 } { queryName2 } { userId2.get } { groupId2.get } { createDate2 } false } val readPreviousQueriesResponse = XmlUtil.stripWhitespace { { queryMasterId1 } { networkQueryId1 } { queryName1 } { createDate1 } { userId1.get } { groupId1.get } { flagged1.get } { flagMessage1.get } { queryMasterId2 } { networkQueryId2 } { queryName2 } { createDate2 } { userId2.get } { groupId2.get } } @Test def testFromI2b2FailsFast() { intercept[Exception] { ReadPreviousQueriesResponse.fromI2b2() } intercept[Exception] { - ReadPreviousQueriesResponse.fromI2b2(ErrorResponse("foo!").toI2b2) + ReadPreviousQueriesResponse.fromI2b2(ErrorResponse(TestProblem("foo!")).toI2b2) } } @Test def testFromXml() { val actual = ReadPreviousQueriesResponse.fromXml(readPreviousQueriesResponse) val expectedQueryMasters = Set(queryMaster1, queryMaster2) actual.queryMasters.toSet should equal(expectedQueryMasters) } @Test def testToXml() { //we compare the string versions of the xml because Scala's xml equality does not always behave properly ReadPreviousQueriesResponse(Seq(queryMaster1, queryMaster2)).toXmlString should equal(readPreviousQueriesResponse.toString) } @Test def testFromI2b2() { val translatedResponse = ReadPreviousQueriesResponse.fromI2b2(response) translatedResponse.queryMasters.toSet should equal(Set(queryMaster1, queryMaster2)) } @Test def testToI2b2() { //Per-queryMaster userids and groupids //we compare the string versions of the xml because Scala's xml equality does not always behave properly val actual = ReadPreviousQueriesResponse(Seq(queryMaster1, queryMaster2)).toI2b2String val expected = response.toString actual should equal(expected) } } \ No newline at end of file diff --git a/commons/protocol/src/test/scala/net/shrine/protocol/ShrineMessageTest.scala b/commons/protocol/src/test/scala/net/shrine/protocol/ShrineMessageTest.scala index bd979d01c..343acf579 100644 --- a/commons/protocol/src/test/scala/net/shrine/protocol/ShrineMessageTest.scala +++ b/commons/protocol/src/test/scala/net/shrine/protocol/ShrineMessageTest.scala @@ -1,166 +1,166 @@ package net.shrine.protocol import net.shrine.problem.TestProblem import net.shrine.util.ShouldMatchersForJUnit import org.junit.Test import scala.xml.NodeSeq import net.shrine.protocol.query.QueryDefinition import net.shrine.protocol.query.Term import net.shrine.util.XmlDateHelper import java.math.BigInteger /** * @author clint * @since Feb 24, 2014 */ final class ShrineMessageTest extends ShouldMatchersForJUnit { @Test def testRoundTrips { val projectId = "salkdjksaljdkla" import scala.concurrent.duration._ val waitTime: Duration = 98374L.milliseconds val userId = "foo-user" val groupId = "foo-group" val authn = AuthenticationInfo("blarg-domain", userId, Credential("sajkhdkjsadh", true)) val queryId = 485794359L val patientSetCollId = "ksaldjksal" val optionsXml: NodeSeq = x val fetchSize = 12345 val queryName = "saljkd;salda" val topicId = "saldjkasljdasdsadsadasdas" val topicName = "Topic Name" val outputTypes = ResultOutputType.nonBreakdownTypes.toSet val queryDefinition = QueryDefinition(queryName, Term("oiweruoiewkldfhsofi")) val queryDefinition2 = QueryDefinition(queryName, Term("a;slkjflfjlsdkjf")) val localResultId = "aoiduaojsdpaojcmsal" val nodeId = NodeId("foo") val nodeId2 = NodeId("bar") val queryTopicId1 = 123L val queryTopicId2 = 456L val queryTopicName1 = "nuh" val queryTopicName2 = "zuh" val shrineNetworkQueryId = 1287698235L val start = Some(XmlDateHelper.now) val end = Some(XmlDateHelper.now) - val singleNodeResult1 = QueryResult.errorResult(Some("blarg"), "glarg",TestProblem) + val singleNodeResult1 = QueryResult.errorResult(Some("blarg"), "glarg",TestProblem()) val singleNodeResult2 = QueryResult( 42L, 99L, Option(ResultOutputType.PATIENT_COUNT_XML), 123L, start, end, Some("description"), QueryResult.StatusType.Finished, Some("status")) val param1 = ParamResponse("foo", "bar", "baz") val queryMaster1 = QueryMaster("kjasdh", 12345L, "name1", userId, groupId, start.get) val queryMaster2 = QueryMaster("skdjlhlasf", 873563L, "name2", userId, groupId, end.get) val queryInstance1 = QueryInstance("asd", "42", userId, groupId, start.get, end.get) val queryInstance2 = QueryInstance("asdasd", "99", userId, groupId, start.get, end.get) val envelope = I2b2ResultEnvelope(DefaultBreakdownResultOutputTypes.PATIENT_AGE_COUNT_XML, Map("x" -> 1, "y" -> 2)) //BroadcastMessage //Non-CA-signed signing cert doMarshallingRoundTrip(BroadcastMessage(123456L, authn, DeleteQueryRequest(projectId, waitTime, authn, queryId), Some(Signature(XmlDateHelper.now, CertId(new BigInteger("1234567890")), None, "asdf".getBytes)))) //CA-signed signing cert doMarshallingRoundTrip(BroadcastMessage(123456L, authn, DeleteQueryRequest(projectId, waitTime, authn, queryId), Some(Signature(XmlDateHelper.now, CertId(new BigInteger("1234567890")), Some(CertData("cert signed by ca".getBytes)), "asdf".getBytes)))) //Non-i2b2able requests doMarshallingRoundTrip(ReadTranslatedQueryDefinitionRequest(authn, waitTime, queryDefinition)) doMarshallingRoundTrip(ReadQueryResultRequest(projectId, waitTime, authn, queryId)) //I2b2able requests doMarshallingRoundTrip(DeleteQueryRequest(projectId, waitTime, authn, queryId)) doMarshallingRoundTrip(ReadApprovedQueryTopicsRequest(projectId, waitTime, authn, userId)) doMarshallingRoundTrip(ReadInstanceResultsRequest(projectId, waitTime, authn, queryId)) doMarshallingRoundTrip(ReadPreviousQueriesRequest(projectId, waitTime, authn, userId, fetchSize)) doMarshallingRoundTrip(ReadQueryDefinitionRequest(projectId, waitTime, authn, queryId)) doMarshallingRoundTrip(ReadQueryInstancesRequest(projectId, waitTime, authn, queryId)) doMarshallingRoundTrip(RenameQueryRequest(projectId, waitTime, authn, queryId, queryName)) doMarshallingRoundTrip(RunQueryRequest(projectId, waitTime, authn, queryId, Option(topicId), Option(topicName), outputTypes, queryDefinition)) doMarshallingRoundTrip(RunQueryRequest(projectId, waitTime, authn, queryId, None, None, outputTypes, queryDefinition)) doMarshallingRoundTrip(ReadResultRequest(projectId, waitTime, authn, localResultId)) //Non-i2b2able responses doMarshallingRoundTrip(SingleNodeReadTranslatedQueryDefinitionResponse(SingleNodeTranslationResult(nodeId, queryDefinition))) doMarshallingRoundTrip(AggregatedReadTranslatedQueryDefinitionResponse(Seq(SingleNodeTranslationResult(nodeId, queryDefinition), SingleNodeTranslationResult(nodeId2, queryDefinition2)))) //I2b2able responses doMarshallingRoundTrip(DeleteQueryResponse(queryId)) doMarshallingRoundTrip(ReadApprovedQueryTopicsResponse(Seq(ApprovedTopic(queryTopicId1, queryTopicName1), ApprovedTopic(queryTopicId2, queryTopicName2)))) doMarshallingRoundTrip(ReadInstanceResultsResponse(shrineNetworkQueryId, singleNodeResult2)) doMarshallingRoundTrip(AggregatedReadInstanceResultsResponse(shrineNetworkQueryId, Seq(singleNodeResult1, singleNodeResult2))) doMarshallingRoundTrip(ReadPdoResponse(Seq(EventResponse("foo", "bar", start, end, Seq(param1))), Seq(PatientResponse("nuh", Seq(param1))), Nil)) doMarshallingRoundTrip(ReadPreviousQueriesResponse(Seq(queryMaster1, queryMaster2))) doMarshallingRoundTrip(ReadQueryDefinitionResponse(42L, "name", userId, start.get, queryDefinition.toXmlString)) doMarshallingRoundTrip(ReadQueryInstancesResponse(42L, userId, groupId, Seq(queryInstance1, queryInstance2))) doMarshallingRoundTrip(RenameQueryResponse(12345L, queryName)) doMarshallingRoundTrip(RunQueryResponse(queryId, start.get, userId, groupId, queryDefinition, 12345L, singleNodeResult1)) doMarshallingRoundTrip(AggregatedRunQueryResponse(queryId, start.get, userId, groupId, queryDefinition, 12345L, Seq(singleNodeResult1, singleNodeResult2))) doMarshallingRoundTrip(ReadResultResponse(42L, singleNodeResult2, envelope)) } private def doMarshallingRoundTrip[T <: ShrineMessage](message: T) { val xml = message.toXml val unmarshalled = ShrineMessage.fromXml(DefaultBreakdownResultOutputTypes.toSet)(xml).get message match { //NB: Special handling of ReadInstanceResultsResponse because its member QueryRequests are munged //before serialization case readInstanceResultsResponse: ReadInstanceResultsResponse => { val unmarshalledResp = unmarshalled.asInstanceOf[ReadInstanceResultsResponse] val expected = readInstanceResultsResponse.copy(singleNodeResult = readInstanceResultsResponse.singleNodeResult.copy(instanceId = readInstanceResultsResponse.shrineNetworkQueryId)) unmarshalledResp should equal(expected) } //NB: Special handling of AggregatedReadInstanceResultsResponse because its member QueryRequests are munged //before serialization case aggReadInstanceResultsResponse: AggregatedReadInstanceResultsResponse => { val unmarshalledResp = unmarshalled.asInstanceOf[AggregatedReadInstanceResultsResponse] val expected = aggReadInstanceResultsResponse.copy(results = aggReadInstanceResultsResponse.results.map(_.copy(instanceId = aggReadInstanceResultsResponse.shrineNetworkQueryId))) unmarshalledResp.results(0).problemDigest should equal(expected.results(0).problemDigest) unmarshalledResp.results(0) should equal(expected.results(0)) unmarshalledResp.results should equal(expected.results) unmarshalledResp should equal(expected) } //NB: Special handling of ReadQueryInstancesResponse because its member QueryInstances are not exactly preserved //on serialization round trips case readQueryInstancesResponse: ReadQueryInstancesResponse => { val unmarshalledResp = unmarshalled.asInstanceOf[ReadQueryInstancesResponse] val expected = unmarshalledResp.withInstances(unmarshalledResp.queryInstances.map(_.copy(queryMasterId = unmarshalledResp.queryMasterId.toString))) } //NB: Special handling of RunQueryResponse because its member QueryRequest is munged //during serialization case runQueryResponse: RunQueryResponse => { val unmarshalledResp = unmarshalled.asInstanceOf[RunQueryResponse] val expected = runQueryResponse.withResult(runQueryResponse.singleNodeResult.copy(instanceId = runQueryResponse.queryInstanceId)) unmarshalledResp should equal(expected) } //NB: Special handling of AggregatedRunQueryResponse because its member QueryRequests are munged //during serialization case aggRunQueryResponse: AggregatedRunQueryResponse => { val unmarshalledResp = unmarshalled.asInstanceOf[AggregatedRunQueryResponse] val expected = aggRunQueryResponse.withResults(aggRunQueryResponse.results.map(_.copy(instanceId = aggRunQueryResponse.queryInstanceId))) unmarshalledResp should equal(expected) } case _ => unmarshalled should equal(message) } } } \ No newline at end of file diff --git a/commons/protocol/src/test/scala/net/shrine/protocol/ShrineResponseTest.scala b/commons/protocol/src/test/scala/net/shrine/protocol/ShrineResponseTest.scala index d676157a4..ecd4515b3 100644 --- a/commons/protocol/src/test/scala/net/shrine/protocol/ShrineResponseTest.scala +++ b/commons/protocol/src/test/scala/net/shrine/protocol/ShrineResponseTest.scala @@ -1,106 +1,106 @@ package net.shrine.protocol import net.shrine.problem.TestProblem import scala.xml.NodeSeq import org.junit.Test import net.shrine.util.ShouldMatchersForJUnit import net.shrine.protocol.query.QueryDefinition import net.shrine.protocol.query.Term import net.shrine.util.XmlDateHelper import net.shrine.util.XmlUtil import scala.util.Success /** * @author clint * @since Nov 5, 2012 */ //noinspection UnitMethodIsParameterless,NameBooleanParameters,ScalaUnnecessaryParentheses final class ShrineResponseTest extends ShouldMatchersForJUnit { @Test def testFromXml { //ShrineResponse.fromXml(null: String).isFailure should be(true) ShrineResponse.fromXml(DefaultBreakdownResultOutputTypes.toSet)(null: NodeSeq).isFailure should be(true) ShrineResponse.fromXml(DefaultBreakdownResultOutputTypes.toSet)(NodeSeq.Empty).isFailure should be(true) def roundTrip(response: ShrineResponse): Unit = { val unmarshalled = ShrineResponse.fromXml(DefaultBreakdownResultOutputTypes.toSet)(response.toXml) unmarshalled.get.getClass should equal(response.getClass) unmarshalled should not be (null) unmarshalled should equal(Success(response)) } val queryResult1 = QueryResult( resultId = 1L, instanceId = 2342L, resultType = Some(ResultOutputType.PATIENT_COUNT_XML), setSize = 123L, startDate = None, endDate = None, description = None, statusType = QueryResult.StatusType.Finished, statusMessage = None) roundTrip(ReadQueryResultResponse(123L, queryResult1)) roundTrip(AggregatedReadQueryResultResponse(123L, Seq(queryResult1))) roundTrip(DeleteQueryResponse(123L)) roundTrip(ReadInstanceResultsResponse(2342L, queryResult1)) roundTrip(AggregatedReadInstanceResultsResponse(2342L, Seq(queryResult1))) roundTrip(ReadPreviousQueriesResponse(Seq(QueryMaster("queryMasterId", 12345L, "name", "userId", "groupId", XmlDateHelper.now, Some(false))))) roundTrip(ReadQueryDefinitionResponse(8457L, "name", "userId", XmlDateHelper.now, "queryDefXml")) roundTrip(ReadQueryInstancesResponse(12345L, "userId", "groupId", Seq.empty)) roundTrip(RenameQueryResponse(12345L, "name")) roundTrip(RunQueryResponse(38957L, XmlDateHelper.now, "userId", "groupId", QueryDefinition("foo", Term("bar")), 2342L, queryResult1)) roundTrip(AggregatedRunQueryResponse(38957L, XmlDateHelper.now, "userId", "groupId", QueryDefinition("foo", Term("bar")), 2342L, Seq(queryResult1))) roundTrip(UnFlagQueryResponse) roundTrip(FlagQueryResponse) - roundTrip(ErrorResponse("errorMessage",Some(TestProblem))) + roundTrip(ErrorResponse(TestProblem("errorMessage"))) } @Test def testToXml { val response = new FooResponse response.toXmlString should equal("") } @Test def testToI2b2 { val expected = XmlUtil.stripWhitespace( 1.1 2.4 SHRINE 1.3-compatible SHRINE 2011-04-08T16:21:12.251-04:00 DONE ) val response = new FooResponse response.toI2b2String should equal(expected.toString()) } private final class FooResponse extends ShrineResponse { protected override def i2b2MessageBody = override def toXml = i2b2MessageBody } } \ No newline at end of file diff --git a/commons/util/src/test/scala/net/shrine/problem/ProblemDigestTest.scala b/commons/util/src/test/scala/net/shrine/problem/ProblemDigestTest.scala index b60492c8b..e84ae7f3e 100644 --- a/commons/util/src/test/scala/net/shrine/problem/ProblemDigestTest.scala +++ b/commons/util/src/test/scala/net/shrine/problem/ProblemDigestTest.scala @@ -1,26 +1,20 @@ package net.shrine.problem import net.shrine.util.ShouldMatchersForJUnit /** * * @author dwalend * @since 1.20 */ final class ProblemDigestTest extends ShouldMatchersForJUnit { def testRoundTrip() = { val problemDigest = ProblemDigest(getClass.getName, "stampText", "Test problem", "A problem for testing",

"We use this problem for testing. Don't worry about it"
) val xml = problemDigest.toXml val fromXml = ProblemDigest.fromXml(xml) fromXml should be(problemDigest) } -} - -object TestProblem extends AbstractProblem(ProblemSources.Unknown) { - override def summary: String = "Test problem summary" - - override def description: String = "Test problem description" -} +} \ No newline at end of file diff --git a/commons/util/src/test/scala/net/shrine/problem/ProblemHandlerTest.scala b/commons/util/src/test/scala/net/shrine/problem/ProblemHandlerTest.scala index 533bfbf19..6b6bde240 100644 --- a/commons/util/src/test/scala/net/shrine/problem/ProblemHandlerTest.scala +++ b/commons/util/src/test/scala/net/shrine/problem/ProblemHandlerTest.scala @@ -1,69 +1,60 @@ package net.shrine.problem import net.shrine.log.Loggable import net.shrine.util.ShouldMatchersForJUnit import org.apache.log4j.Level import scala.collection.mutable.{Map => MMap} /** * * @author dwalend * @since 1.20 */ final class ProblemHandlerTest extends ShouldMatchersForJUnit { def testProblemHandler() = { val loggable = new MockLoggable - case class TestProblem(nodeName:String,summary:String,exception:Exception) extends AbstractProblem(ProblemSources.Hub) { - - val message = s"TestProblem involving $nodeName" - - val description = summary + message - - override def throwable = Some(exception) - } - val fakeException = new RuntimeException("test exception") fakeException.fillInStackTrace() - val problem = TestProblem("testProblem","Problem created for testing",fakeException) + val problem = TestProblem("testProblem","Problem created for testing",Some(fakeException)) val problemHandler = LoggingProblemHandler problemHandler.handleProblem(problem) loggable.loggedAt(Level.ERROR) should be (right = true) } private final class MockLoggable extends Loggable { val loggedAt: MMap[Level, Boolean] = MMap.empty override def debug(s: => Any) { loggedAt(Level.DEBUG) = true super.debug(s) } override def info(s: => Any) { loggedAt(Level.INFO) = true super.info(s) } override def warn(s: => Any) { loggedAt(Level.WARN) = true super.warn(s) } override def error(s: => Any) { loggedAt(Level.ERROR) = true super.error(s) } } } \ No newline at end of file diff --git a/commons/util/src/test/scala/net/shrine/problem/TestProblem.scala b/commons/util/src/test/scala/net/shrine/problem/TestProblem.scala new file mode 100644 index 000000000..eeffb2e1b --- /dev/null +++ b/commons/util/src/test/scala/net/shrine/problem/TestProblem.scala @@ -0,0 +1,9 @@ +package net.shrine.problem + +/** + * @author david + * @since 1.22 + */ +case class TestProblem(override val summary: String = "test summary", + override val description:String = "test description", + override val throwable: Option[Throwable] = None) extends AbstractProblem(ProblemSources.Unknown) diff --git a/hub/broadcaster-aggregator/src/test/scala/net/shrine/aggregation/ReadInstanceResultsAggregatorTest.scala b/hub/broadcaster-aggregator/src/test/scala/net/shrine/aggregation/ReadInstanceResultsAggregatorTest.scala index 5c1faf6f3..bdc8f3529 100644 --- a/hub/broadcaster-aggregator/src/test/scala/net/shrine/aggregation/ReadInstanceResultsAggregatorTest.scala +++ b/hub/broadcaster-aggregator/src/test/scala/net/shrine/aggregation/ReadInstanceResultsAggregatorTest.scala @@ -1,107 +1,103 @@ package net.shrine.aggregation -import net.shrine.problem.ProblemNotYetEncoded -import org.junit.Test -import org.junit.Assert.assertNotNull -import net.shrine.protocol.{ ErrorResponse, QueryResult, ReadInstanceResultsResponse } +import net.shrine.problem.TestProblem import net.shrine.protocol.ResultOutputType._ -import net.shrine.util.XmlDateHelper -import net.shrine.protocol.AggregatedReadInstanceResultsResponse -import net.shrine.protocol.Result -import net.shrine.protocol.NodeId -import net.shrine.util.ShouldMatchersForJUnit +import net.shrine.protocol.{AggregatedReadInstanceResultsResponse, ErrorResponse, NodeId, QueryResult, ReadInstanceResultsResponse, Result} +import net.shrine.util.{ShouldMatchersForJUnit, XmlDateHelper} +import org.junit.Assert.assertNotNull +import org.junit.Test /** * @author Bill Simons * @since 6/13/11 * @see http://cbmi.med.harvard.edu * @see http://chip.org *

* NOTICE: This software comes with NO guarantees whatsoever and is * licensed as Lgpl Open Source * @see http://www.gnu.org/licenses/lgpl.html */ //noinspection UnitMethodIsParameterless,NameBooleanParameters final class ReadInstanceResultsAggregatorTest extends ShouldMatchersForJUnit { import scala.concurrent.duration._ @Test def testAggregate { val instanceId = 123L val startDate = XmlDateHelper.now val endDate = XmlDateHelper.now val queryResult1 = new QueryResult(1L, instanceId, PATIENT_COUNT_XML, 12, startDate, endDate, QueryResult.StatusType.Finished) val queryResult2 = new QueryResult(2L, instanceId, PATIENT_COUNT_XML, 14, startDate, endDate, QueryResult.StatusType.Finished) val aggregator = new ReadInstanceResultsAggregator(instanceId, true) val aggregatorNoAggregate = new ReadInstanceResultsAggregator(instanceId, false) val response1 = ReadInstanceResultsResponse(instanceId, queryResult1) val response2 = ReadInstanceResultsResponse(instanceId, queryResult2) val description1 = "NODE1" val description2 = "NODE2" val result1 = Result(NodeId(description1), 1.second, response1) val result2 = Result(NodeId(description2), 5.seconds, response2) { val actual = aggregator.aggregate(Seq(result1, result2), Nil).asInstanceOf[AggregatedReadInstanceResultsResponse] assertNotNull(actual) assertNotNull(actual.results) actual.results.size should equal(3) val expectedTotal = queryResult1.setSize + queryResult2.setSize actual.results.contains(queryResult1.withDescription(description1)) should be(true) actual.results.contains(queryResult2.withDescription(description2).withResultType(PATIENT_COUNT_XML)) should be(true) actual.results.exists(qr => qr.setSize == expectedTotal && qr.resultTypeIs(PATIENT_COUNT_XML) && qr.description.contains("Aggregated Count")) should be(true) } { val actual = aggregatorNoAggregate.aggregate(Seq(result1, result2), Nil).asInstanceOf[AggregatedReadInstanceResultsResponse] assertNotNull(actual) assertNotNull(actual.results) actual.results.size should equal(2) actual.results.contains(queryResult1.withDescription(description1)) should be(true) actual.results.contains(queryResult2.withDescription(description2).withResultType(PATIENT_COUNT_XML)) should be(true) } } @Test def testAggregateWithError { val instanceId = 123L val startDate = XmlDateHelper.now val endDate = XmlDateHelper.now val queryResult = new QueryResult(1L, instanceId, PATIENT_COUNT_XML, 12, startDate, endDate, QueryResult.StatusType.Finished) val aggregator = new ReadInstanceResultsAggregator(instanceId, true) val errorMessage = "you are an error" val patientCountResponse = ReadInstanceResultsResponse(instanceId, queryResult) - val errorResponse = ErrorResponse(errorMessage) + val errorResponse = ErrorResponse(TestProblem(errorMessage)) val patientCountNodeDescription = "NODE1" val errorNodeDescription = "NODE2" val result1 = Result(NodeId(patientCountNodeDescription), 1.minute, patientCountResponse) val result2 = Result(NodeId(errorNodeDescription), 1.hour, errorResponse) val actual = aggregator.aggregate(Seq(result1, result2), Nil).asInstanceOf[AggregatedReadInstanceResultsResponse] assertNotNull(actual) assertNotNull(actual.results) actual.results.size should equal(3) actual.results.contains(queryResult.withDescription(patientCountNodeDescription)) should be(true) - actual.results.exists(qr => qr.problemDigest.exists(pd => pd.codec == classOf[ProblemNotYetEncoded].getName)) should be (true) + actual.results.exists(qr => qr.problemDigest.exists(pd => pd.codec == classOf[TestProblem].getName)) should be (true) } } \ No newline at end of file diff --git a/hub/broadcaster-aggregator/src/test/scala/net/shrine/aggregation/ReadQueryResultAggregatorTest.scala b/hub/broadcaster-aggregator/src/test/scala/net/shrine/aggregation/ReadQueryResultAggregatorTest.scala index 19a38977a..b65e2dfcb 100644 --- a/hub/broadcaster-aggregator/src/test/scala/net/shrine/aggregation/ReadQueryResultAggregatorTest.scala +++ b/hub/broadcaster-aggregator/src/test/scala/net/shrine/aggregation/ReadQueryResultAggregatorTest.scala @@ -1,134 +1,125 @@ package net.shrine.aggregation -import net.shrine.problem.ProblemNotYetEncoded - -import scala.concurrent.duration.DurationInt -import org.junit.Test +import net.shrine.problem.TestProblem +import net.shrine.protocol.{AggregatedReadQueryResultResponse, BaseShrineResponse, ErrorResponse, NodeId, QueryResult, ReadQueryResultResponse, Result, ResultOutputType} import net.shrine.util.ShouldMatchersForJUnit -import net.shrine.protocol.AggregatedReadQueryResultResponse -import net.shrine.protocol.ErrorResponse -import net.shrine.protocol.NodeId -import net.shrine.protocol.QueryResult -import net.shrine.protocol.ReadQueryResultResponse -import net.shrine.protocol.Result -import net.shrine.protocol.ResultOutputType -import net.shrine.protocol.BaseShrineResponse +import org.junit.Test /** * @author clint * @since Nov 7, 2012 */ final class ReadQueryResultAggregatorTest extends ShouldMatchersForJUnit { private val queryId = 12345L import ResultOutputType._ private def asAggregatedResponse(resp: BaseShrineResponse) = resp.asInstanceOf[AggregatedReadQueryResultResponse] private val setSize1 = 123L private val setSize2 = 456L private val totalSetSize = setSize1 + setSize2 private val queryResult1 = QueryResult(1L, 2L, Some(PATIENT_COUNT_XML), setSize1, None, None, None, QueryResult.StatusType.Finished, None) private val queryResult2 = QueryResult(1L, 2L, Some(PATIENT_COUNT_XML), setSize2, None, None, None, QueryResult.StatusType.Finished, None) private val response1 = ReadQueryResultResponse(queryId, queryResult1) private val response2 = ReadQueryResultResponse(queryId, queryResult2) import scala.concurrent.duration._ private val result1 = Result(NodeId("X"), 1.second, response1) private val result2 = Result(NodeId("Y"), 1.second, response2) - private val errors = Seq(ErrorResponse("blarg"), ErrorResponse("glarg")) + private val errors = Seq(ErrorResponse(TestProblem(summary ="blarg")), ErrorResponse(TestProblem(summary = "glarg"))) @Test def testAggregate { val aggregator = new ReadQueryResultAggregator(queryId, true) val response = asAggregatedResponse(aggregator.aggregate(Seq(result1, result2), Nil)) val Seq(actualQueryResult1, actualQueryResult2, aggregatedQueryResult) = response.results actualQueryResult1 should equal(queryResult1) actualQueryResult2 should equal(queryResult2) val expectedAggregatedResult = queryResult1.withSetSize(totalSetSize).withInstanceId(queryId).withDescription("Aggregated Count") aggregatedQueryResult should equal(expectedAggregatedResult) } @Test def testAggregateNoAggregatedResult { val aggregator = new ReadQueryResultAggregator(queryId, false) val response = asAggregatedResponse(aggregator.aggregate(Seq(result1, result2), Nil)) val Seq(actualQueryResult1, actualQueryResult2) = response.results actualQueryResult1 should equal(queryResult1) actualQueryResult2 should equal(queryResult2) } @Test def testAggregateNoResponses { for (doAggregation <- Seq(true, false)) { val aggregator = new ReadQueryResultAggregator(queryId, true) val response = asAggregatedResponse(aggregator.aggregate(Nil, Nil)) response.queryId should equal(queryId) response.results.isEmpty should be(true) } } @Test def testAggregateOnlyErrorResponses { val aggregator = new ReadQueryResultAggregator(queryId, true) val response = asAggregatedResponse(aggregator.aggregate(Nil, errors)) response.queryId should equal(queryId) - response.results.exists(qr => qr.problemDigest.exists(pd => pd.codec == classOf[ProblemNotYetEncoded].getName)) should be (true) + response.results.exists(qr => qr.problemDigest.exists(pd => pd.codec == classOf[TestProblem].getName)) should be (true) } @Test def testAggregateSomeErrors { val aggregator = new ReadQueryResultAggregator(queryId, true) val response = asAggregatedResponse(aggregator.aggregate(Seq(result1, result2), errors)) val Seq(actualQueryResult1, actualQueryResult2, aggregatedQueryResult, actualErrorQueryResults @ _*) = response.results actualQueryResult1 should equal(queryResult1) actualQueryResult2 should equal(queryResult2) val expectedAggregatedResult = queryResult1.withSetSize(totalSetSize).withInstanceId(queryId).withDescription("Aggregated Count") aggregatedQueryResult should equal(expectedAggregatedResult) - actualErrorQueryResults.exists(qr => qr.problemDigest.exists(pd => pd.codec == classOf[ProblemNotYetEncoded].getName)) should be (true) + actualErrorQueryResults.exists(qr => qr.problemDigest.exists(pd => pd.codec == classOf[TestProblem].getName)) should be (true) } @Test def testAggregateSomeDownstreamErrors { val aggregator = new ReadQueryResultAggregator(queryId, true) val result3 = Result(NodeId("A"), 1.second, errors.head) val result4 = Result(NodeId("A"), 1.second, errors.last) val response = asAggregatedResponse(aggregator.aggregate(Seq(result1, result2, result3, result4), Nil)) val Seq(actualQueryResult1, actualQueryResult2, aggregatedQueryResult, actualErrorQueryResults @ _*) = response.results actualQueryResult1 should equal(queryResult1) actualQueryResult2 should equal(queryResult2) val expectedAggregatedResult = queryResult1.withSetSize(totalSetSize).withInstanceId(queryId).withDescription("Aggregated Count") aggregatedQueryResult should equal(expectedAggregatedResult) actualErrorQueryResults.forall(qr => qr.description.contains("A")) should be(true) } } \ No newline at end of file diff --git a/hub/broadcaster-aggregator/src/test/scala/net/shrine/aggregation/RunQueryAggregatorTest.scala b/hub/broadcaster-aggregator/src/test/scala/net/shrine/aggregation/RunQueryAggregatorTest.scala index 859fc729a..8a2387f1e 100644 --- a/hub/broadcaster-aggregator/src/test/scala/net/shrine/aggregation/RunQueryAggregatorTest.scala +++ b/hub/broadcaster-aggregator/src/test/scala/net/shrine/aggregation/RunQueryAggregatorTest.scala @@ -1,148 +1,150 @@ package net.shrine.aggregation +import net.shrine.problem.TestProblem + import scala.concurrent.duration.DurationInt import org.junit.Test import net.shrine.util.ShouldMatchersForJUnit import net.shrine.protocol.AggregatedRunQueryResponse import net.shrine.protocol.ErrorResponse import net.shrine.protocol.I2b2ResultEnvelope import net.shrine.protocol.NodeId import net.shrine.protocol.QueryResult import net.shrine.protocol.Result import net.shrine.protocol.ResultOutputType.PATIENT_COUNT_XML import net.shrine.protocol.RunQueryResponse import net.shrine.protocol.query.QueryDefinition import net.shrine.protocol.query.Term import net.shrine.util.XmlDateHelper import net.shrine.protocol.DefaultBreakdownResultOutputTypes /** * * * @author Justin Quan * @see http://chip.org * Date: 8/12/11 */ final class RunQueryAggregatorTest extends ShouldMatchersForJUnit { private val queryId = 1234L private val queryName = "someQueryName" private val now = XmlDateHelper.now private val userId = "user" private val groupId = "group" private val requestQueryDef = QueryDefinition(queryName, Term("""\\i2b2\i2b2\Demographics\Age\0-9 years old\""")) private val requestQueryDefString = requestQueryDef.toI2b2String private val queryInstanceId = 9999L import scala.concurrent.duration._ @Test def testAggregate { val qrCount = new QueryResult(1L, queryInstanceId, PATIENT_COUNT_XML, 10L, now, now, "Desc", QueryResult.StatusType.Finished) val rqr1 = RunQueryResponse(queryId, now, userId, groupId, requestQueryDef, queryInstanceId, qrCount) val result1 = Result(NodeId("description2"), 1.second, rqr1) val aggregator = new RunQueryAggregator(queryId, userId, groupId, requestQueryDef, true) val actual = aggregator.aggregate(Vector(result1), Nil).asInstanceOf[AggregatedRunQueryResponse] actual.queryId should equal(queryId) actual.queryInstanceId should equal(-1L) actual.results.size should equal(2) actual.results.filter(_.resultTypeIs(PATIENT_COUNT_XML)).size should equal(2) //1 for the actual count result, 1 for the aggregated total count actual.results.filter(hasTotalCount).size should equal(1) actual.results.filter(hasTotalCount).head.setSize should equal(10) actual.queryName should equal(queryName) } @Test def testAggCount { val qrSet = new QueryResult(2L, queryInstanceId, PATIENT_COUNT_XML, 10L, now, now, "Desc", QueryResult.StatusType.Finished) val rqr1 = RunQueryResponse(queryId, now, userId, groupId, requestQueryDef, queryInstanceId, qrSet) val rqr2 = RunQueryResponse(queryId, now, userId, groupId, requestQueryDef, queryInstanceId, qrSet) val result1 = Result(NodeId("description1"), 1.second, rqr1) val result2 = Result(NodeId("description2"), 1.second, rqr2) val aggregator = new RunQueryAggregator(queryId, userId, groupId, requestQueryDef, true) //TODO: test handling error responses val actual = aggregator.aggregate(Vector(result1, result2), Nil).asInstanceOf[AggregatedRunQueryResponse] actual.results.filter(_.description.getOrElse("").equalsIgnoreCase("TOTAL COUNT")).head.setSize should equal(20) } @Test def testHandleErrorResponse { val qrCount = new QueryResult(1L, queryInstanceId, PATIENT_COUNT_XML, 10L, now, now, "Desc", QueryResult.StatusType.Finished) val rqr1 = RunQueryResponse(queryId, now, userId, groupId, requestQueryDef, queryInstanceId, qrCount) val errorMessage = "error message" - val errorResponse = ErrorResponse(errorMessage) + val errorResponse = ErrorResponse(TestProblem(summary = errorMessage)) val result1 = Result(NodeId("description1"), 1.second, rqr1) val result2 = Result(NodeId("description2"), 1.second, errorResponse) val aggregator = new RunQueryAggregator(queryId, userId, groupId, requestQueryDef, true) val actual = aggregator.aggregate(Vector(result1, result2), Nil).asInstanceOf[AggregatedRunQueryResponse] actual.results.size should equal(3) actual.results.filter(_.resultTypeIs(PATIENT_COUNT_XML)).head.setSize should equal(10) actual.results.filter(_.statusType == QueryResult.StatusType.Error).head.statusMessage should equal(Some(errorMessage)) actual.results.filter(hasTotalCount).head.setSize should equal(10) } @Test def testAggregateResponsesWithBreakdowns { def toColumnTuple(i: Int) = ("x" + i, i.toLong) val breakdowns1 = Map.empty ++ DefaultBreakdownResultOutputTypes.values.map { resultType => resultType -> I2b2ResultEnvelope(resultType, (1 to 10).map(toColumnTuple).toMap) } val breakdowns2 = Map.empty ++ DefaultBreakdownResultOutputTypes.values.map { resultType => resultType -> I2b2ResultEnvelope(resultType, (11 to 20).map(toColumnTuple).toMap) } val qr1 = new QueryResult(1L, queryInstanceId, Some(PATIENT_COUNT_XML), 10L, Some(now), Some(now), Some("Desc"), QueryResult.StatusType.Finished, None, breakdowns = breakdowns1) val qr2 = new QueryResult(2L, queryInstanceId, Some(PATIENT_COUNT_XML), 20L, Some(now), Some(now), Some("Desc"), QueryResult.StatusType.Finished, None, breakdowns = breakdowns2) val rqr1 = RunQueryResponse(queryId, now, userId, groupId, requestQueryDef, queryInstanceId, qr1) val rqr2 = RunQueryResponse(queryId, now, userId, groupId, requestQueryDef, queryInstanceId, qr2) val result1 = Result(NodeId("description2"), 1.second, rqr1) val result2 = Result(NodeId("description1"), 1.second, rqr2) val aggregator = new RunQueryAggregator(queryId, userId, groupId, requestQueryDef, true) val actual = aggregator.aggregate(Seq(result1, result2), Nil).asInstanceOf[AggregatedRunQueryResponse] actual.results.size should equal(3) actual.results.filter(hasTotalCount).size should equal(1) val Seq(actualQr1, actualQr2, actualQr3) = actual.results.filter(_.resultTypeIs(PATIENT_COUNT_XML)) actualQr1.setSize should equal(10) actualQr2.setSize should equal(20) actualQr3.setSize should equal(30) actualQr1.breakdowns should equal(breakdowns1) actualQr2.breakdowns should equal(breakdowns2) actualQr3.breakdowns.isEmpty should be(true) } private def hasTotalCount(result: QueryResult) = result.description.getOrElse("").equalsIgnoreCase("TOTAL COUNT") private def toQueryResultMap(results: QueryResult*) = Map.empty ++ (for { result <- results resultType <- result.resultType } yield (resultType, result)) } diff --git a/hub/broadcaster-aggregator/src/test/scala/net/shrine/broadcaster/HubBroadcastServiceTest.scala b/hub/broadcaster-aggregator/src/test/scala/net/shrine/broadcaster/HubBroadcastServiceTest.scala index 700cc38e8..acdf16070 100644 --- a/hub/broadcaster-aggregator/src/test/scala/net/shrine/broadcaster/HubBroadcastServiceTest.scala +++ b/hub/broadcaster-aggregator/src/test/scala/net/shrine/broadcaster/HubBroadcastServiceTest.scala @@ -1,100 +1,88 @@ package net.shrine.broadcaster +import net.shrine.aggregation.Aggregator import net.shrine.problem.TestProblem +import net.shrine.protocol.{AuthenticationInfo, BroadcastMessage, Credential, DeleteQueryRequest, ErrorResponse, Failure, NodeId, Result, ShrineResponse, SingleNodeResult, Timeout} +import net.shrine.util.ShouldMatchersForJUnit +import org.junit.Test import scala.concurrent.Await -import org.junit.Test -import net.shrine.util.ShouldMatchersForJUnit -import net.shrine.aggregation.Aggregator -import net.shrine.crypto.DefaultSignerVerifier -import net.shrine.crypto.TestKeystore -import net.shrine.protocol.AuthenticationInfo -import net.shrine.protocol.BroadcastMessage -import net.shrine.protocol.Credential -import net.shrine.protocol.DeleteQueryRequest -import net.shrine.protocol.ErrorResponse -import net.shrine.protocol.Failure -import net.shrine.protocol.NodeId -import net.shrine.protocol.Result -import net.shrine.protocol.ShrineResponse -import net.shrine.protocol.SingleNodeResult -import net.shrine.protocol.Timeout -import net.shrine.broadcaster.dao.MockHubDao /** * @author clint * @since Nov 19, 2013 */ final class HubBroadcastAndAggregationServiceTest extends AbstractSquerylHubDaoTest with ShouldMatchersForJUnit { - import scala.concurrent.duration._ import MockBroadcasters._ - private def result(description: Char) = Result(NodeId(description.toString), 1.second, ErrorResponse("blah blah blah",Some(TestProblem))) + import scala.concurrent.duration._ + + private def result(description: Char) = Result(NodeId(description.toString), 1.second, ErrorResponse(TestProblem(summary = "blah blah blah"))) private val results = "abcde".map(result) private lazy val nullResultsByOrigin: Map[NodeId, SingleNodeResult] = Map(NodeId("X") -> null, NodeId("Y") -> null) private lazy val resultsWithNullsByOrigin: Map[NodeId, SingleNodeResult] = { results.collect { case r @ Result(origin, _, _) => origin -> r }.toMap ++ nullResultsByOrigin } private val broadcastMessage = { val authn = AuthenticationInfo("domain", "username", Credential("asdasd", false)) import scala.concurrent.duration._ BroadcastMessage(authn, DeleteQueryRequest("projectId", 12345.milliseconds, authn, 12345L)) } @Test def testAggregateHandlesNullResults { val mockBroadcaster = MockAdapterClientBroadcaster(resultsWithNullsByOrigin) val broadcastService = new HubBroadcastAndAggregationService(InJvmBroadcasterClient(mockBroadcaster)) val aggregator: Aggregator = new Aggregator { override def aggregate(results: Iterable[SingleNodeResult], errors: Iterable[ErrorResponse]): ShrineResponse = { - ErrorResponse(results.size.toString,Some(TestProblem)) + ErrorResponse(TestProblem(summary = results.size.toString)) } } val aggregatedResult = Await.result(broadcastService.sendAndAggregate(broadcastMessage, aggregator, true), 5.minutes) mockBroadcaster.messageParam.signature.isDefined should be(false) - aggregatedResult should equal(ErrorResponse(s"${results.size}",Some(TestProblem))) + aggregatedResult should equal(ErrorResponse(TestProblem(summary = results.size.toString))) } @Test def testAggregateHandlesFailures { - def toResult(description: Char) = Result(NodeId(description.toString), 1.second, ErrorResponse("blah blah blah")) + def toResult(description: Char) = Result(NodeId(description.toString), 1.second, ErrorResponse(TestProblem(summary = "blah blah blah"))) def toFailure(description: Char) = Failure(NodeId(description.toString), new Exception with scala.util.control.NoStackTrace) val failuresByOrigin: Map[NodeId, SingleNodeResult] = { "UV".map(toFailure).map { case f @ Failure(origin, _) => origin -> f }.toMap } val timeoutsByOrigin: Map[NodeId, SingleNodeResult] = Map(NodeId("Z") -> Timeout(NodeId("Z"))) val resultsWithFailuresByOrigin: Map[NodeId, SingleNodeResult] = resultsWithNullsByOrigin ++ failuresByOrigin ++ timeoutsByOrigin val mockBroadcaster = MockAdapterClientBroadcaster(resultsWithFailuresByOrigin) val broadcastService = new HubBroadcastAndAggregationService(InJvmBroadcasterClient(mockBroadcaster)) val aggregator: Aggregator = new Aggregator { override def aggregate(results: Iterable[SingleNodeResult], errors: Iterable[ErrorResponse]): ShrineResponse = { - ErrorResponse(s"${results.size},${errors.size}",Some(TestProblem)) + ErrorResponse(TestProblem(summary = s"${results.size},${errors.size}")) } } val aggregatedResult = Await.result(broadcastService.sendAndAggregate(broadcastMessage, aggregator, true), 5.minutes) mockBroadcaster.messageParam.signature.isDefined should be(false) - aggregatedResult should equal(ErrorResponse(s"${results.size + failuresByOrigin.size + timeoutsByOrigin.size},0",Some(TestProblem))) + aggregatedResult should equal(ErrorResponse(TestProblem(summary = s"${results.size + failuresByOrigin.size + timeoutsByOrigin.size},0"))) } } diff --git a/hub/broadcaster-aggregator/src/test/scala/net/shrine/broadcaster/SigningBroadcastAndAggregationServiceTest.scala b/hub/broadcaster-aggregator/src/test/scala/net/shrine/broadcaster/SigningBroadcastAndAggregationServiceTest.scala index 28f37e2e2..561476d7a 100644 --- a/hub/broadcaster-aggregator/src/test/scala/net/shrine/broadcaster/SigningBroadcastAndAggregationServiceTest.scala +++ b/hub/broadcaster-aggregator/src/test/scala/net/shrine/broadcaster/SigningBroadcastAndAggregationServiceTest.scala @@ -1,102 +1,102 @@ package net.shrine.broadcaster import net.shrine.problem.TestProblem import scala.concurrent.Await import org.junit.Test import net.shrine.util.ShouldMatchersForJUnit import net.shrine.aggregation.Aggregator import net.shrine.crypto.DefaultSignerVerifier import net.shrine.crypto.TestKeystore import net.shrine.protocol.AuthenticationInfo import net.shrine.protocol.BroadcastMessage import net.shrine.protocol.Credential import net.shrine.protocol.DeleteQueryRequest import net.shrine.protocol.ErrorResponse import net.shrine.protocol.Failure import net.shrine.protocol.NodeId import net.shrine.protocol.Result import net.shrine.protocol.ShrineResponse import net.shrine.protocol.SingleNodeResult import net.shrine.protocol.Timeout import net.shrine.crypto.SigningCertStrategy import net.shrine.broadcaster.dao.MockHubDao /** * @author clint * @since Nov 19, 2013 */ final class SigningBroadcastAndAggregationServiceTest extends ShouldMatchersForJUnit { import scala.concurrent.duration._ import MockBroadcasters._ - private def result(description: Char) = Result(NodeId(description.toString), 1.second, ErrorResponse("blah blah blah",Some(TestProblem))) + private def result(description: Char) = Result(NodeId(description.toString), 1.second, ErrorResponse(TestProblem(summary = "blah blah blah"))) private val results = "abcde".map(result) private lazy val nullResultsByOrigin: Map[NodeId, SingleNodeResult] = Map(NodeId("X") -> null, NodeId("Y") -> null) private lazy val resultsWithNullsByOrigin: Map[NodeId, SingleNodeResult] = { results.collect { case r @ Result(origin, _, _) => origin -> r }.toMap ++ nullResultsByOrigin } private lazy val signer = new DefaultSignerVerifier(TestKeystore.certCollection) private val broadcastMessage = { val authn = AuthenticationInfo("domain", "username", Credential("asdasd", false)) import scala.concurrent.duration._ BroadcastMessage(authn, DeleteQueryRequest("projectId", 12345.milliseconds, authn, 12345L)) } @Test def testAggregateHandlesNullResults { val mockBroadcaster = MockAdapterClientBroadcaster(resultsWithNullsByOrigin) val broadcastService = SigningBroadcastAndAggregationService(InJvmBroadcasterClient(mockBroadcaster), signer, SigningCertStrategy.Attach) val aggregator: Aggregator = new Aggregator { override def aggregate(results: Iterable[SingleNodeResult], errors: Iterable[ErrorResponse]): ShrineResponse = { - ErrorResponse(results.size.toString,Some(TestProblem)) + ErrorResponse(TestProblem(results.size.toString)) } } val aggregatedResult = Await.result(broadcastService.sendAndAggregate(broadcastMessage, aggregator, true), 5.minutes) mockBroadcaster.messageParam.signature.isDefined should be(true) - aggregatedResult should equal(ErrorResponse(s"${results.size}",Some(TestProblem))) + aggregatedResult should equal(ErrorResponse(TestProblem(s"${results.size}"))) } @Test def testAggregateHandlesFailures { - def toResult(description: Char) = Result(NodeId(description.toString), 1.second, ErrorResponse("blah blah blah",Some(TestProblem))) + def toResult(description: Char) = Result(NodeId(description.toString), 1.second, ErrorResponse(TestProblem("blah blah blah"))) def toFailure(description: Char) = Failure(NodeId(description.toString), new Exception with scala.util.control.NoStackTrace) val failuresByOrigin: Map[NodeId, SingleNodeResult] = { "UV".map(toFailure).map { case f @ Failure(origin, _) => origin -> f }.toMap } val timeoutsByOrigin: Map[NodeId, SingleNodeResult] = Map(NodeId("Z") -> Timeout(NodeId("Z"))) val resultsWithFailuresByOrigin: Map[NodeId, SingleNodeResult] = resultsWithNullsByOrigin ++ failuresByOrigin ++ timeoutsByOrigin val mockBroadcaster = MockAdapterClientBroadcaster(resultsWithFailuresByOrigin) val broadcastService = SigningBroadcastAndAggregationService(InJvmBroadcasterClient(mockBroadcaster), signer, SigningCertStrategy.DontAttach) val aggregator: Aggregator = new Aggregator { override def aggregate(results: Iterable[SingleNodeResult], errors: Iterable[ErrorResponse]): ShrineResponse = { - ErrorResponse(s"${results.size},${errors.size}",Some(TestProblem)) + ErrorResponse(TestProblem(s"${results.size},${errors.size}")) } } val aggregatedResult = Await.result(broadcastService.sendAndAggregate(broadcastMessage, aggregator, true), 5.minutes) mockBroadcaster.messageParam.signature.isDefined should be(true) - aggregatedResult should equal(ErrorResponse(s"${results.size + failuresByOrigin.size + timeoutsByOrigin.size},0",Some(TestProblem))) + aggregatedResult should equal(ErrorResponse(TestProblem(s"${results.size + failuresByOrigin.size + timeoutsByOrigin.size},0"))) } } diff --git a/qep/service/src/test/scala/net/shrine/qep/queries/QepQueryDbTest.scala b/qep/service/src/test/scala/net/shrine/qep/queries/QepQueryDbTest.scala index b8c75829f..8369d13d4 100644 --- a/qep/service/src/test/scala/net/shrine/qep/queries/QepQueryDbTest.scala +++ b/qep/service/src/test/scala/net/shrine/qep/queries/QepQueryDbTest.scala @@ -1,237 +1,237 @@ package net.shrine.qep.queries import net.shrine.protocol.QueryResult.StatusType import net.shrine.protocol.{I2b2ResultEnvelope, DefaultBreakdownResultOutputTypes, QueryResult, ResultOutputType} import net.shrine.util.{XmlDateHelper, ShouldMatchersForJUnit} import org.junit.{After, Before, Test} import net.shrine.problem.TestProblem /** * @author david * @since 1/20/16 */ class QepQueryDbTest extends ShouldMatchersForJUnit { val qepQuery = QepQuery( networkId = 1L, userName = "ben", userDomain = "testDomain", queryName = "testQuery", expression = Some("testExpression"), dateCreated = System.currentTimeMillis(), deleted = false, queryXml = "testXML", changeDate = System.currentTimeMillis() ) val secondQepQuery = QepQuery( networkId = 2L, userName = "dave", userDomain = "testDomain", queryName = "testQuery", expression = Some("testExpression"), deleted = false, dateCreated = System.currentTimeMillis(), queryXml = "testXML", changeDate = System.currentTimeMillis() ) val flag = QepQueryFlag( networkQueryId = 1L, flagged = true, flagMessage = "This query is flagged", changeDate = System.currentTimeMillis() ) @Test def testInsertQepQuery() { QepQueryDb.db.insertQepQuery(qepQuery) QepQueryDb.db.insertQepQuery(secondQepQuery) val results = QepQueryDb.db.selectAllQepQueries results should equal(Seq(qepQuery,secondQepQuery)) } @Test def testSelectQepQueriesForUser() { QepQueryDb.db.insertQepQuery(qepQuery) QepQueryDb.db.insertQepQuery(secondQepQuery) val results = QepQueryDb.db.selectPreviousQueriesByUserAndDomain("ben","testDomain",100) results should equal(Seq(qepQuery)) } @Test def testSelectQueryFlags() { val results1 = QepQueryDb.db.selectMostRecentQepQueryFlagsFor(Set(1L,2L)) results1 should equal(Map.empty) QepQueryDb.db.insertQepQueryFlag(flag) val results2 = QepQueryDb.db.selectMostRecentQepQueryFlagsFor(Set(1L,2L)) results2 should equal(Map(1L -> flag)) } val qepResultRowFromExampleCom = QueryResultRow( resultId = 10L, networkQueryId = 1L, instanceId = 100L, adapterNode = "example.com", resultType = Some(ResultOutputType.PATIENT_COUNT_XML), size = 30L, startDate = Some(System.currentTimeMillis() - 60), endDate = Some(System.currentTimeMillis() - 30), status = QueryResult.StatusType.Finished, statusMessage = None, changeDate = System.currentTimeMillis() ) @Test def testInsertQueryResultRow() { QepQueryDb.db.insertQepResultRow(qepResultRowFromExampleCom) val results = QepQueryDb.db.selectMostRecentQepResultRowsFor(1L) results should equal(Seq(qepResultRowFromExampleCom)) } val queryResult = QueryResult( resultId = 20L, instanceId = 200L, resultType = Some(ResultOutputType.PATIENT_COUNT_XML), setSize = 2000L, startDate = Some(XmlDateHelper.now), endDate = Some(XmlDateHelper.now), description = Some("example.com"), statusType = StatusType.Finished, statusMessage = None ) @Test def testInsertQueryResult(): Unit = { QepQueryDb.db.insertQueryResult(2L,queryResult) val results = QepQueryDb.db.selectMostRecentQepResultsFor(2L) results should equal(Seq(queryResult)) } val qepResultRowFromExampleComInThePast = QueryResultRow( resultId = 8L, networkQueryId = 1L, instanceId = 100L, adapterNode = "example.com", resultType = Some(ResultOutputType.PATIENT_COUNT_XML), size = 0L, startDate = qepResultRowFromExampleCom.startDate, endDate = None, status = QueryResult.StatusType.Processing, statusMessage = None, changeDate = qepResultRowFromExampleCom.changeDate - 40 ) val qepResultRowFromGeneralHospital = QueryResultRow( resultId = 100L, networkQueryId = 1L, instanceId = 100L, adapterNode = "generalhospital.org", resultType = Some(ResultOutputType.PATIENT_COUNT_XML), size = 100L, startDate = Some(System.currentTimeMillis() - 60), endDate = Some(System.currentTimeMillis() - 30), status = QueryResult.StatusType.Finished, statusMessage = None, changeDate = System.currentTimeMillis() ) @Test def testGetMostRecentResultRows() { QepQueryDb.db.insertQepResultRow(qepResultRowFromExampleComInThePast) QepQueryDb.db.insertQepResultRow(qepResultRowFromGeneralHospital) QepQueryDb.db.insertQepResultRow(qepResultRowFromExampleCom) val results = QepQueryDb.db.selectMostRecentQepResultRowsFor(1L) results.to[Set] should equal(Set(qepResultRowFromExampleCom,qepResultRowFromGeneralHospital)) } val maleRow = QepQueryBreakdownResultsRow( networkQueryId = 1L, adapterNode = "example.com", resultId = 100L, resultType = DefaultBreakdownResultOutputTypes.PATIENT_GENDER_COUNT_XML, dataKey = "male", value = 388, changeDate = System.currentTimeMillis() ) val femaleRow = QepQueryBreakdownResultsRow( networkQueryId = 1L, adapterNode = "example.com", resultId = 100L, resultType = DefaultBreakdownResultOutputTypes.PATIENT_GENDER_COUNT_XML, dataKey = "female", value = 390, changeDate = System.currentTimeMillis() ) val unknownRow = QepQueryBreakdownResultsRow( networkQueryId = 1L, adapterNode = "example.com", resultId = 100L, resultType = DefaultBreakdownResultOutputTypes.PATIENT_GENDER_COUNT_XML, dataKey = "unknown", value = 4, changeDate = System.currentTimeMillis() ) @Test def testInsertBreakdownRows(): Unit = { QepQueryDb.db.insertQueryBreakdown(maleRow) QepQueryDb.db.insertQueryBreakdown(femaleRow) QepQueryDb.db.insertQueryBreakdown(unknownRow) val results = QepQueryDb.db.selectAllBreakdownResultsRows results.to[Set] should equal(Set(maleRow,femaleRow,unknownRow)) } val breakdowns = Map(DefaultBreakdownResultOutputTypes.PATIENT_GENDER_COUNT_XML -> I2b2ResultEnvelope(DefaultBreakdownResultOutputTypes.PATIENT_GENDER_COUNT_XML,Map("male" -> 3000,"female" -> 4000,"unknown" -> 234))) @Test def testInsertQueryResultWithBreakdowns(): Unit = { val queryResultWithBreakdowns = queryResult.copy(breakdowns = breakdowns) QepQueryDb.db.insertQueryResult(2L,queryResultWithBreakdowns) val results = QepQueryDb.db.selectMostRecentQepResultsFor(2L) results should equal(Seq(queryResultWithBreakdowns)) } @Test def testInsertQueryResultWithProblem(): Unit = { - val queryResultWithProblem = queryResult.copy(statusType = StatusType.Error,problemDigest = Some(TestProblem.toDigest)) + val queryResultWithProblem = queryResult.copy(statusType = StatusType.Error,problemDigest = Some(TestProblem().toDigest)) QepQueryDb.db.insertQueryResult(2L,queryResultWithProblem) val results = QepQueryDb.db.selectMostRecentQepResultsFor(2L) results should equal(Seq(queryResultWithProblem)) } @Before def beforeEach() = { QepQueryDb.db.createTables() } @After def afterEach() = { QepQueryDb.db.dropTables() } }