diff --git a/.clj-kondo/config.edn b/.clj-kondo/config.edn index 3fdb744be..238186c25 100644 --- a/.clj-kondo/config.edn +++ b/.clj-kondo/config.edn @@ -1,5 +1,5 @@ {:lint-as - {blaze.test-util/with-system clojure.core/with-open} + {blaze.module.test-util/with-system clojure.core/with-open} :linters {:unsorted-required-namespaces diff --git a/.github/scripts/authenticated-request.sh b/.github/scripts/authenticated-request.sh index 6ca8f07d5..0c86939b1 100755 --- a/.github/scripts/authenticated-request.sh +++ b/.github/scripts/authenticated-request.sh @@ -10,15 +10,15 @@ fi BASE="http://localhost:8080/fhir" if [ "200" = "$(curl -s --oauth2-bearer "$ACCESS_TOKEN" -o /dev/null -w '%{response_code}' "$BASE")" ]; then - echo "OK: successful authenticated system search request" + echo "OK ๐Ÿ‘: successful authenticated system search request" else - echo "Fail: failed authenticated system search request" + echo "Fail ๐Ÿ˜ž: failed authenticated system search request" exit 1 fi if [ "200" = "$(curl -s --oauth2-bearer "$ACCESS_TOKEN" -H "Content-Type: application/fhir+json" -d @.github/openid-auth-test/batch-bundle.json "$BASE" | jq -r '.entry[].response.status')" ]; then - echo "OK: successful authenticated batch request" + echo "OK ๐Ÿ‘: successful authenticated batch request" else - echo "Fail: failed authenticated batch request" + echo "Fail ๐Ÿ˜ž: failed authenticated batch request" exit 1 fi diff --git a/.github/scripts/batch-metadata.sh b/.github/scripts/batch-metadata.sh index 8aaebe59d..af90b5fcb 100755 --- a/.github/scripts/batch-metadata.sh +++ b/.github/scripts/batch-metadata.sh @@ -26,32 +26,32 @@ RESULT=$(curl -sH "Content-Type: application/fhir+json" -d "$(bundle)" "$BASE") RESOURCE_TYPE="$(echo "$RESULT" | jq -r .resourceType)" if [ "$RESOURCE_TYPE" = "Bundle" ]; then - echo "OK: the resource type is Bundle" + echo "OK ๐Ÿ‘: the resource type is Bundle" else - echo "Fail: the resource type is $RESOURCE_TYPE, expected Bundle" + echo "Fail ๐Ÿ˜ž: the resource type is $RESOURCE_TYPE, expected Bundle" exit 1 fi BUNDLE_TYPE="$(echo "$RESULT" | jq -r .type)" if [ "$BUNDLE_TYPE" = "batch-response" ]; then - echo "OK: the bundle type is batch-response" + echo "OK ๐Ÿ‘: the bundle type is batch-response" else - echo "Fail: the bundle type is $BUNDLE_TYPE, expected batch-response" + echo "Fail ๐Ÿ˜ž: the bundle type is $BUNDLE_TYPE, expected batch-response" exit 1 fi RESPONSE_STATUS="$(echo "$RESULT" | jq -r .entry[].response.status)" if [ "$RESPONSE_STATUS" = "200" ]; then - echo "OK: the response status is 200" + echo "OK ๐Ÿ‘: the response status is 200" else - echo "Fail: the response status is $RESPONSE_STATUS, expected 200" + echo "Fail ๐Ÿ˜ž: the response status is $RESPONSE_STATUS, expected 200" exit 1 fi RESPONSE_RESOURCE_TYPE="$(echo "$RESULT" | jq -r .entry[].resource.resourceType)" if [ "$RESPONSE_RESOURCE_TYPE" = "CapabilityStatement" ]; then - echo "OK: resource type is CapabilityStatement" + echo "OK ๐Ÿ‘: resource type is CapabilityStatement" else - echo "Fail: resource type was $RESPONSE_RESOURCE_TYPE but should be CapabilityStatement" + echo "Fail ๐Ÿ˜ž: resource type was $RESPONSE_RESOURCE_TYPE but should be CapabilityStatement" exit 1 fi diff --git a/.github/scripts/batch.sh b/.github/scripts/batch.sh index bb3d9cc25..3f3a4cf16 100755 --- a/.github/scripts/batch.sh +++ b/.github/scripts/batch.sh @@ -29,32 +29,32 @@ RESULT=$(curl -sH "Content-Type: application/fhir+json" -d "$(bundle)" "$BASE") RESOURCE_TYPE="$(echo "$RESULT" | jq -r .resourceType)" if [ "$RESOURCE_TYPE" = "Bundle" ]; then - echo "OK: the resource type is Bundle" + echo "OK ๐Ÿ‘: the resource type is Bundle" else - echo "Fail: the resource type is $RESOURCE_TYPE, expected Bundle" + echo "Fail ๐Ÿ˜ž: the resource type is $RESOURCE_TYPE, expected Bundle" exit 1 fi BUNDLE_TYPE="$(echo "$RESULT" | jq -r .type)" if [ "$BUNDLE_TYPE" = "batch-response" ]; then - echo "OK: the bundle type is batch-response" + echo "OK ๐Ÿ‘: the bundle type is batch-response" else - echo "Fail: the bundle type is $BUNDLE_TYPE, expected batch-response" + echo "Fail ๐Ÿ˜ž: the bundle type is $BUNDLE_TYPE, expected batch-response" exit 1 fi RESPONSE_STATUS="$(echo "$RESULT" | jq -r .entry[].response.status)" if [ "$RESPONSE_STATUS" = "200" ]; then - echo "OK: the response status is 200" + echo "OK ๐Ÿ‘: the response status is 200" else - echo "Fail: the response status is $RESPONSE_STATUS, expected 200" + echo "Fail ๐Ÿ˜ž: the response status is $RESPONSE_STATUS, expected 200" exit 1 fi RESPONSE_PATIENT_ID="$(echo "$RESULT" | jq -r .entry[].resource.id)" if [ "$RESPONSE_PATIENT_ID" = "$PATIENT_ID" ]; then - echo "OK: patient id's match" + echo "OK ๐Ÿ‘: patient id's match" else - echo "Fail: response patient id was $RESPONSE_PATIENT_ID but should be $PATIENT_ID" + echo "Fail ๐Ÿ˜ž: response patient id was $RESPONSE_PATIENT_ID but should be $PATIENT_ID" exit 1 fi diff --git a/.github/scripts/chaining-without-referential-integrity.sh b/.github/scripts/chaining-without-referential-integrity.sh index b2d07db2d..e4b442314 100755 --- a/.github/scripts/chaining-without-referential-integrity.sh +++ b/.github/scripts/chaining-without-referential-integrity.sh @@ -8,8 +8,8 @@ curl -sXPUT -d '{"resourceType" : "Patient", "id": "0", "gender": "male"}' -H 'C RESULT="$(curl -sH 'Prefer: handling=strict' -H 'Accept: application/fhir+json' "$BASE/Observation?patient.gender=male&_summary=count" | jq -r '.total')" if [ "$RESULT" = "1" ]; then - echo "Success: chaining works" + echo "OK ๐Ÿ‘: chaining works" else - echo "Fail: chaining doesn't work" + echo "Fail ๐Ÿ˜ž: chaining doesn't work" exit 1 fi diff --git a/.github/scripts/check-date-search.sh b/.github/scripts/check-date-search.sh index 50b11f9ea..d8e04edd0 100755 --- a/.github/scripts/check-date-search.sh +++ b/.github/scripts/check-date-search.sh @@ -20,7 +20,7 @@ size() { if [ "$DOWNLOAD_SIZE" = "$COUNT_SIZE" ]; then echo "$DOWNLOAD_SIZE" else - echo "Fail: the download size is $DOWNLOAD_SIZE, expected $COUNT_SIZE" + echo "Fail ๐Ÿ˜ž: the download size is $DOWNLOAD_SIZE, expected $COUNT_SIZE" exit 1 fi } diff --git a/.github/scripts/check-referential-integrity-enforced.sh b/.github/scripts/check-referential-integrity-enforced.sh index 39b9fd3b6..57f423ab5 100755 --- a/.github/scripts/check-referential-integrity-enforced.sh +++ b/.github/scripts/check-referential-integrity-enforced.sh @@ -3,8 +3,8 @@ ENFORCED=$(curl -s http://localhost:8080/fhir/metadata | jq -r 'isempty(.rest[].resource[].referencePolicy[] | select(. == "enforced")) | not') if [ "true" = "$ENFORCED" ]; then - echo "Success" + echo "OK ๐Ÿ‘" else - echo "Fail" + echo "Fail ๐Ÿ˜ž" exit 1 fi diff --git a/.github/scripts/check-referential-integrity-not-enforced.sh b/.github/scripts/check-referential-integrity-not-enforced.sh index f5faeee88..86179be6c 100755 --- a/.github/scripts/check-referential-integrity-not-enforced.sh +++ b/.github/scripts/check-referential-integrity-not-enforced.sh @@ -3,8 +3,8 @@ ENFORCED=$(curl -s http://localhost:8080/fhir/metadata | jq -r 'isempty(.rest[].resource[].referencePolicy[] | select(. == "enforced")) | not') if [ "false" = "$ENFORCED" ]; then - echo "Success" + echo "OK ๐Ÿ‘" else - echo "Fail" + echo "Fail ๐Ÿ˜ž" exit 1 fi diff --git a/.github/scripts/conditional-create.sh b/.github/scripts/conditional-create.sh index 730951dea..2b487f99c 100755 --- a/.github/scripts/conditional-create.sh +++ b/.github/scripts/conditional-create.sh @@ -34,9 +34,9 @@ STATUS=$(curl -sH "Content-Type: application/fhir+json" \ -d "$(bundle)" "$BASE" | jq -r '.entry[].response.status') if [ "$STATUS" = "201" ]; then - echo "OK: first attempt created the Organization" + echo "OK ๐Ÿ‘: first attempt created the Organization" else - echo "Fail: status was ${STATUS} but should be 201" + echo "Fail ๐Ÿ˜ž: status was ${STATUS} but should be 201" exit 1 fi @@ -44,8 +44,8 @@ STATUS=$(curl -sH "Content-Type: application/fhir+json" \ -d "$(bundle)" "$BASE" | jq -r '.entry[].response.status') if [ "$STATUS" = "200" ]; then - echo "OK: second attempt returned the already created Organization" + echo "OK ๐Ÿ‘: second attempt returned the already created Organization" else - echo "Fail: status was ${STATUS} but should be 200" + echo "Fail ๐Ÿ˜ž: status was ${STATUS} but should be 200" exit 1 fi diff --git a/.github/scripts/delete.sh b/.github/scripts/delete.sh index 639b58ed2..9b991f2d8 100755 --- a/.github/scripts/delete.sh +++ b/.github/scripts/delete.sh @@ -8,33 +8,33 @@ PATIENT_HISTORY=$(curl -s "$BASE/Patient/$PATIENT_ID/_history") TOTAL=$(echo "$PATIENT_HISTORY" | jq .total) if [ "$TOTAL" = "1" ]; then - echo "OK: patient history has one entry" + echo "OK ๐Ÿ‘: patient history has one entry" else - echo "Fail: patient history has $TOTAL entries" + echo "Fail ๐Ÿ˜ž: patient history has $TOTAL entries" exit 1 fi METHOD=$(echo "$PATIENT_HISTORY" | jq -r .entry[].request.method) if [ "$METHOD" = "DELETE" ]; then - echo "OK: patient history entry has method DELETE" + echo "OK ๐Ÿ‘: patient history entry has method DELETE" else - echo "Fail: patient history entry has method $METHOD" + echo "Fail ๐Ÿ˜ž: patient history entry has method $METHOD" exit 1 fi STATUS=$(echo "$PATIENT_HISTORY" | jq -r .entry[].response.status) if [ "$STATUS" = "204" ]; then - echo "OK: patient history entry has status 204" + echo "OK ๐Ÿ‘: patient history entry has status 204" else - echo "Fail: patient history entry has status $STATUS" + echo "Fail ๐Ÿ˜ž: patient history entry has status $STATUS" exit 1 fi PATIENT_STATUS=$(curl -is "$BASE/Patient/$PATIENT_ID" | grep HTTP | tr -d '\r\n') if [ "$PATIENT_STATUS" = "HTTP/1.1 410 Gone" ]; then - echo "OK: patient status is HTTP/1.1 410 Gone" + echo "OK ๐Ÿ‘: patient status is HTTP/1.1 410 Gone" else - echo "Fail: patient status is $PATIENT_STATUS" + echo "Fail ๐Ÿ˜ž: patient status is $PATIENT_STATUS" exit 1 fi @@ -42,8 +42,8 @@ PATIENT_OUTCOME=$(curl -s "$BASE/Patient/$PATIENT_ID") CODE=$(echo "$PATIENT_OUTCOME" | jq -r .issue[].code) if [ "$CODE" = "deleted" ]; then - echo "OK: patient outcome has code deleted" + echo "OK ๐Ÿ‘: patient outcome has code deleted" else - echo "Fail: patient outcome has code $CODE" + echo "Fail ๐Ÿ˜ž: patient outcome has code $CODE" exit 1 fi diff --git a/.github/scripts/download-resources-query-sort.sh b/.github/scripts/download-resources-query-sort.sh index e498ebd21..6b77c9020 100755 --- a/.github/scripts/download-resources-query-sort.sh +++ b/.github/scripts/download-resources-query-sort.sh @@ -11,9 +11,9 @@ blazectl --no-progress --server "$BASE" download "$TYPE" -q "_sort=$SORT&$QUERY" SIZE=$(wc -l "$FILE_NAME_PREFIX-get".ndjson | xargs | cut -d ' ' -f1) if [ "$EXPECTED_SIZE" = "$SIZE" ]; then - echo "Success: download size matches for GET request" + echo "OK ๐Ÿ‘: download size matches for GET request" else - echo "Fail: download size was ${SIZE} but should be ${EXPECTED_SIZE} for GET request" + echo "Fail ๐Ÿ˜ž: download size was ${SIZE} but should be ${EXPECTED_SIZE} for GET request" exit 1 fi @@ -21,16 +21,16 @@ blazectl --server "$BASE" download "$TYPE" -p -q "_sort=$SORT&$QUERY" -o "$FILE_ SIZE=$(wc -l "$FILE_NAME_PREFIX-post".ndjson | xargs | cut -d ' ' -f1) if [ "$EXPECTED_SIZE" = "$SIZE" ]; then - echo "Success: download size matches for POST request" + echo "OK ๐Ÿ‘: download size matches for POST request" else - echo "Fail: download size was ${SIZE} but should be ${EXPECTED_SIZE} for POST request" + echo "Fail ๐Ÿ˜ž: download size was ${SIZE} but should be ${EXPECTED_SIZE} for POST request" exit 1 fi if [ "$(diff "$FILE_NAME_PREFIX-get.ndjson" "$FILE_NAME_PREFIX-post.ndjson")" = "" ]; then - echo "Success: both downloads are identical" + echo "OK ๐Ÿ‘: both downloads are identical" else - echo "Fail: the GET and the POST download differ" + echo "Fail ๐Ÿ˜ž: the GET and the POST download differ" exit 1 fi @@ -42,8 +42,8 @@ else LAST_UPDATED_SORT=$(echo "$LAST_UPDATED" | sort) fi if [ "$LAST_UPDATED" = "$LAST_UPDATED_SORT" ]; then - echo "Success: resources are sorted" + echo "OK ๐Ÿ‘: resources are sorted" else - echo "Fail: resources are not sorted" + echo "Fail ๐Ÿ˜ž: resources are not sorted" exit 1 fi diff --git a/.github/scripts/download-resources-query.sh b/.github/scripts/download-resources-query.sh index 2a98d7576..24d1ffb5c 100755 --- a/.github/scripts/download-resources-query.sh +++ b/.github/scripts/download-resources-query.sh @@ -19,9 +19,9 @@ blazectl --no-progress --server "$BASE" download "$TYPE" -q "$QUERY" -o "$FILE_N SIZE=$(wc -l "$FILE_NAME_PREFIX-get".ndjson | xargs | cut -d ' ' -f1) if [ "$EXPECTED_SIZE" = "$SIZE" ]; then - echo "Success: download size matches for GET request" + echo "OK ๐Ÿ‘: download size matches for GET request" else - echo "Fail: download size was ${SIZE} but should be ${EXPECTED_SIZE} for GET request" + echo "Fail ๐Ÿ˜ž: download size was ${SIZE} but should be ${EXPECTED_SIZE} for GET request" exit 1 fi @@ -29,15 +29,15 @@ blazectl --server "$BASE" download "$TYPE" -p -q "$QUERY" -o "$FILE_NAME_PREFIX- SIZE=$(wc -l "$FILE_NAME_PREFIX-post".ndjson | xargs | cut -d ' ' -f1) if [ "$EXPECTED_SIZE" = "$SIZE" ]; then - echo "Success: download size matches for POST request" + echo "OK ๐Ÿ‘: download size matches for POST request" else - echo "Fail: download size was ${SIZE} but should be ${EXPECTED_SIZE} for POST request" + echo "Fail ๐Ÿ˜ž: download size was ${SIZE} but should be ${EXPECTED_SIZE} for POST request" exit 1 fi if [ "$(diff "$FILE_NAME_PREFIX-get.ndjson" "$FILE_NAME_PREFIX-post.ndjson")" = "" ]; then - echo "Success: both downloads are identical" + echo "OK ๐Ÿ‘: both downloads are identical" else - echo "Fail: the GET and the POST download differ" + echo "Fail ๐Ÿ˜ž: the GET and the POST download differ" exit 1 fi diff --git a/.github/scripts/evaluate-measure-blazectl-stratifier.sh b/.github/scripts/evaluate-measure-blazectl-stratifier.sh index c388320d1..a46edd6a5 100755 --- a/.github/scripts/evaluate-measure-blazectl-stratifier.sh +++ b/.github/scripts/evaluate-measure-blazectl-stratifier.sh @@ -8,9 +8,9 @@ REPORT=$(blazectl --server "$BASE" evaluate-measure ".github/scripts/cql/$NAME.y COUNT=$(echo "$REPORT" | jq '.group[0].population[0].count') if [ "$COUNT" = "$EXPECTED_COUNT" ]; then - echo "Success: count ($COUNT) equals the expected count" + echo "OK ๐Ÿ‘: count ($COUNT) equals the expected count" else - echo "Fail: count ($COUNT) != $EXPECTED_COUNT" + echo "Fail ๐Ÿ˜ž: count ($COUNT) != $EXPECTED_COUNT" exit 1 fi @@ -18,9 +18,9 @@ STRATIFIER_DATA=$(echo "$REPORT" | jq -r '.group[0].stratifier[0].stratum[] | [. EXPECTED_STRATIFIER_DATA=$(cat ".github/scripts/cql/$NAME.csv") if [ "$STRATIFIER_DATA" = "$EXPECTED_STRATIFIER_DATA" ]; then - echo "Success: stratifier data equals the expected stratifier data" + echo "OK ๐Ÿ‘: stratifier data equals the expected stratifier data" else - echo "Fail: stratifier data differs" + echo "Fail ๐Ÿ˜ž: stratifier data differs" echo "$STRATIFIER_DATA" exit 1 fi diff --git a/.github/scripts/evaluate-measure-blazectl.sh b/.github/scripts/evaluate-measure-blazectl.sh index 96ea962e1..e728b789a 100755 --- a/.github/scripts/evaluate-measure-blazectl.sh +++ b/.github/scripts/evaluate-measure-blazectl.sh @@ -7,8 +7,8 @@ EXPECTED_COUNT="$2" COUNT=$(blazectl --server "$BASE" evaluate-measure ".github/scripts/cql/$NAME.yml" 2> /dev/null | jq '.group[0].population[0].count') if [ "$COUNT" = "$EXPECTED_COUNT" ]; then - echo "Success: count ($COUNT) equals the expected count" + echo "OK ๐Ÿ‘: count ($COUNT) equals the expected count" else - echo "Fail: count ($COUNT) != $EXPECTED_COUNT" + echo "Fail ๐Ÿ˜ž: count ($COUNT) != $EXPECTED_COUNT" exit 1 fi diff --git a/.github/scripts/evaluate-measure-subject-list.sh b/.github/scripts/evaluate-measure-subject-list.sh index 6ae7fcb47..d36ef3f3f 100755 --- a/.github/scripts/evaluate-measure-subject-list.sh +++ b/.github/scripts/evaluate-measure-subject-list.sh @@ -121,9 +121,9 @@ REPORT=$(evaluate-measure "$BASE" "$MEASURE_ID") COUNT=$(echo "$REPORT" | jq -r ".group[0].population[0].count") if [ "$COUNT" = "$EXPECTED_COUNT" ]; then - echo "Success: count ($COUNT) equals the expected count" + echo "OK ๐Ÿ‘: count ($COUNT) equals the expected count" else - echo "Fail: count ($COUNT) != $EXPECTED_COUNT" + echo "Fail ๐Ÿ˜ž: count ($COUNT) != $EXPECTED_COUNT" echo "Report:" echo "$REPORT" | jq . exit 1 @@ -134,9 +134,9 @@ PATIENT_BUNDLE=$(fetch-patients "$BASE" "$LIST_ID") ID_COUNT=$(echo "$PATIENT_BUNDLE" | jq -r ".entry[].resource.id" | sort -u | wc -l | xargs) if [ "$ID_COUNT" = "$EXPECTED_COUNT" ]; then - echo "Success: downloaded patient count ($ID_COUNT) equals the expected count" + echo "OK ๐Ÿ‘: downloaded patient count ($ID_COUNT) equals the expected count" else - echo "Fail: downloaded patient count ($ID_COUNT) != $EXPECTED_COUNT" + echo "Fail ๐Ÿ˜ž: downloaded patient count ($ID_COUNT) != $EXPECTED_COUNT" echo "Patient bundle:" echo "$PATIENT_BUNDLE" | jq . exit 1 diff --git a/.github/scripts/evaluate-measure-timeout.sh b/.github/scripts/evaluate-measure-timeout.sh index 0875b29e1..0ed605c03 100755 --- a/.github/scripts/evaluate-measure-timeout.sh +++ b/.github/scripts/evaluate-measure-timeout.sh @@ -6,8 +6,8 @@ NAME="$1" DIAGNOSTICS=$(blazectl --server "$BASE" evaluate-measure ".github/scripts/cql/$NAME.yml" 2> /dev/null | grep Diagnostics | cut -d: -f2 | xargs) if [ "$DIAGNOSTICS" = "Timeout of 10 millis eclipsed while evaluating." ]; then - echo "Success: timeout happened" + echo "OK ๐Ÿ‘: timeout happened" else - echo "Fail: no timeout" + echo "Fail ๐Ÿ˜ž: no timeout" exit 1 fi diff --git a/.github/scripts/evaluate-measure.sh b/.github/scripts/evaluate-measure.sh index 5020a851a..f062a9f9e 100755 --- a/.github/scripts/evaluate-measure.sh +++ b/.github/scripts/evaluate-measure.sh @@ -95,9 +95,9 @@ REPORT=$(evaluate-measure "$BASE" "$MEASURE_ID") COUNT=$(echo "$REPORT" | jq -r ".group[0].population[0].count") if [ "$COUNT" = "$EXPECTED_COUNT" ]; then - echo "Success: count ($COUNT) equals the expected count" + echo "OK ๐Ÿ‘: count ($COUNT) equals the expected count" else - echo "Fail: count ($COUNT) != $EXPECTED_COUNT" + echo "Fail ๐Ÿ˜ž: count ($COUNT) != $EXPECTED_COUNT" echo "Report:" echo "$REPORT" | jq . exit 1 diff --git a/.github/scripts/evaluate-patient-q1-measure.sh b/.github/scripts/evaluate-patient-q1-measure.sh index 9a3675397..d781efaf1 100755 --- a/.github/scripts/evaluate-patient-q1-measure.sh +++ b/.github/scripts/evaluate-patient-q1-measure.sh @@ -88,17 +88,17 @@ MEASURE_ID=$(create-measure "$MEASURE_URI" "$LIBRARY_URI" | post "$BASE" "Measur MALE_PATIENT_ID=$(curl -s "$BASE/Patient?gender=male&_count=1" | jq -r '.entry[].resource.id') COUNT=$(evaluate-measure "$BASE" "$MEASURE_ID" "$MALE_PATIENT_ID" | jq -r ".group[0].population[0].count") if [ "$COUNT" = "1" ]; then - echo "Success: count ($COUNT) equals the expected count" + echo "OK ๐Ÿ‘: count ($COUNT) equals the expected count" else - echo "Fail: count ($COUNT) != 1" + echo "Fail ๐Ÿ˜ž: count ($COUNT) != 1" exit 1 fi FEMALE_PATIENT_ID=$(curl -s "$BASE/Patient?gender=female&_count=1" | jq -r ".entry[].resource.id") COUNT=$(evaluate-measure "$BASE" "$MEASURE_ID" "$FEMALE_PATIENT_ID" | jq -r ".group[0].population[0].count") if [ "$COUNT" = "0" ]; then - echo "Success: count ($COUNT) equals the expected count" + echo "OK ๐Ÿ‘: count ($COUNT) equals the expected count" else - echo "Fail: count ($COUNT) != 0" + echo "Fail ๐Ÿ˜ž: count ($COUNT) != 0" exit 1 fi diff --git a/.github/scripts/forwarded-header.sh b/.github/scripts/forwarded-header.sh index 670651b9d..119b54d0b 100755 --- a/.github/scripts/forwarded-header.sh +++ b/.github/scripts/forwarded-header.sh @@ -5,8 +5,8 @@ EXPECTED_SELF_LINK="$PROTO://blaze.de/fhir/Patient" ACTUAL_SELF_LINK=$(curl -s -H "Forwarded:host=blaze.de;proto=$PROTO" http://localhost:8080/fhir/Patient | jq -r .link[0].url | cut -d? -f1) if [ "$EXPECTED_SELF_LINK" = "$ACTUAL_SELF_LINK" ]; then - echo "Success" + echo "OK ๐Ÿ‘" else - echo "Fail: expected '$EXPECTED_SELF_LINK' but was '$ACTUAL_SELF_LINK'" + echo "Fail ๐Ÿ˜ž: expected '$EXPECTED_SELF_LINK' but was '$ACTUAL_SELF_LINK'" exit 1 fi diff --git a/.github/scripts/include-without-referential-integrity.sh b/.github/scripts/include-without-referential-integrity.sh index af44acc93..ae87c96ab 100755 --- a/.github/scripts/include-without-referential-integrity.sh +++ b/.github/scripts/include-without-referential-integrity.sh @@ -8,8 +8,8 @@ curl -sXPUT -d '{"resourceType" : "Patient", "id": "0"}' -H 'Content-Type: appli RESULT=$(curl -s "$BASE/Observation?_include=Observation:subject" | jq -r '.entry[].search.mode' | tr '\n' '|') if [ "$RESULT" = "match|include|" ]; then - echo "Success: include works" + echo "OK ๐Ÿ‘: include works" else - echo "Fail: include doesn't work" + echo "Fail ๐Ÿ˜ž: include doesn't work" exit 1 fi diff --git a/.github/scripts/not-acceptable.sh b/.github/scripts/not-acceptable.sh index 3e3b763cc..19222e584 100755 --- a/.github/scripts/not-acceptable.sh +++ b/.github/scripts/not-acceptable.sh @@ -3,8 +3,8 @@ BASE="http://localhost:8080/fhir" if [ "406" = "$(curl -s -o /dev/null -w '%{response_code}' -H 'Accept: text/plain' "$BASE")" ]; then - echo "OK: text/plain is a not acceptable media type" + echo "OK ๐Ÿ‘: text/plain is a not acceptable media type" else - echo "Fail" + echo "Fail ๐Ÿ˜ž" exit 1 fi diff --git a/.github/scripts/revinclude.sh b/.github/scripts/revinclude.sh index 0b87aac40..6a5b4b1f1 100755 --- a/.github/scripts/revinclude.sh +++ b/.github/scripts/revinclude.sh @@ -18,20 +18,20 @@ ACTUAL_NUM_PROCEDURES=$(jq -r .resourceType output.ndjson | grep -c Procedure) rm output.ndjson if [ "$EXPECTED_NUM_PATIENTS" != "$ACTUAL_NUM_PATIENTS" ]; then - echo "Fail: Patient download size was ${ACTUAL_NUM_PATIENTS} but should be ${EXPECTED_NUM_PATIENTS}" + echo "Fail ๐Ÿ˜ž: Patient download size was ${ACTUAL_NUM_PATIENTS} but should be ${EXPECTED_NUM_PATIENTS}" exit 1 elif [ "$EXPECTED_NUM_OBSERVATIONS" != "$ACTUAL_NUM_OBSERVATIONS" ]; then - echo "Fail: Observation download size was ${ACTUAL_NUM_OBSERVATIONS} but should be ${EXPECTED_NUM_OBSERVATIONS}" + echo "Fail ๐Ÿ˜ž: Observation download size was ${ACTUAL_NUM_OBSERVATIONS} but should be ${EXPECTED_NUM_OBSERVATIONS}" exit 1 elif [ "$EXPECTED_NUM_CONDITIONS" != "$ACTUAL_NUM_CONDITIONS" ]; then - echo "Fail: Condition download size was ${ACTUAL_NUM_CONDITIONS} but should be ${EXPECTED_NUM_CONDITIONS}" + echo "Fail ๐Ÿ˜ž: Condition download size was ${ACTUAL_NUM_CONDITIONS} but should be ${EXPECTED_NUM_CONDITIONS}" exit 1 elif [ "$EXPECTED_NUM_ENCOUNTERS" != "$ACTUAL_NUM_ENCOUNTERS" ]; then - echo "Fail: Encounter download size was ${ACTUAL_NUM_ENCOUNTERS} but should be ${EXPECTED_NUM_ENCOUNTERS}" + echo "Fail ๐Ÿ˜ž: Encounter download size was ${ACTUAL_NUM_ENCOUNTERS} but should be ${EXPECTED_NUM_ENCOUNTERS}" exit 1 elif [ "$EXPECTED_NUM_PROCEDURES" != "$ACTUAL_NUM_PROCEDURES" ]; then - echo "Fail: Procedure download size was ${ACTUAL_NUM_PROCEDURES} but should be ${EXPECTED_NUM_PROCEDURES}" + echo "Fail ๐Ÿ˜ž: Procedure download size was ${ACTUAL_NUM_PROCEDURES} but should be ${EXPECTED_NUM_PROCEDURES}" exit 1 else - echo "Success: all download sizes match" + echo "OK ๐Ÿ‘: all download sizes match" fi diff --git a/.github/scripts/search-compartment.sh b/.github/scripts/search-compartment.sh index a718fd903..9fdec3d10 100755 --- a/.github/scripts/search-compartment.sh +++ b/.github/scripts/search-compartment.sh @@ -5,8 +5,8 @@ PATIENT_ID=$(curl -s "$BASE/Patient?identifier=http://hl7.org/fhir/sid/us-ssn|99 OBSERVATION_COUNT=$(curl -s "$BASE/Patient/$PATIENT_ID/Observation?_summary=count" | jq .total) if [ "$OBSERVATION_COUNT" = "1277" ]; then - echo "Success: lab count ($OBSERVATION_COUNT) equals the expected count" + echo "OK ๐Ÿ‘: lab count ($OBSERVATION_COUNT) equals the expected count" else - echo "Fail: lab count ($OBSERVATION_COUNT) != 1277" + echo "Fail ๐Ÿ˜ž: lab count ($OBSERVATION_COUNT) != 1277" exit 1 fi diff --git a/.github/scripts/search-observation-profile.sh b/.github/scripts/search-observation-profile.sh index 83c9d92c1..9f9d66b7e 100755 --- a/.github/scripts/search-observation-profile.sh +++ b/.github/scripts/search-observation-profile.sh @@ -4,8 +4,8 @@ BASE="http://localhost:8080/fhir" LAB_COUNT=$(curl -s "$BASE/Observation?_profile=http://hl7.org/fhir/us/core/StructureDefinition/us-core-observation-lab&_summary=count" | jq -r .total) if [ "$LAB_COUNT" = "27218" ]; then - echo "Success: lab count ($LAB_COUNT) equals the expected count" + echo "OK ๐Ÿ‘: lab count ($LAB_COUNT) equals the expected count" else - echo "Fail: lab count ($LAB_COUNT) != 27218" + echo "Fail ๐Ÿ˜ž: lab count ($LAB_COUNT) != 27218" exit 1 fi diff --git a/.github/scripts/search-patient-last-updated.sh b/.github/scripts/search-patient-last-updated.sh index 6c052e81a..6451bad2d 100755 --- a/.github/scripts/search-patient-last-updated.sh +++ b/.github/scripts/search-patient-last-updated.sh @@ -11,8 +11,8 @@ NOW=$(date +%Y-%m-%dT%H:%M:%S) PATIENT_COUNT=$(curl -sH 'Prefer: handling=strict' "$BASE/Patient?_lastUpdated=gt$NOW&_summary=count" | jq -r .total) if [ "$PATIENT_COUNT" -eq 0 ]; then - echo "Success: no patents are updated after $NOW" + echo "OK ๐Ÿ‘: no patents are updated after $NOW" else - echo "Fail: $PATIENT_COUNT patents are updated after $NOW" + echo "Fail ๐Ÿ˜ž: $PATIENT_COUNT patents are updated after $NOW" exit 1 fi diff --git a/.github/scripts/util.sh b/.github/scripts/util.sh index 3342000b7..f121bcbe7 100644 --- a/.github/scripts/util.sh +++ b/.github/scripts/util.sh @@ -2,18 +2,18 @@ test() { if [ "$2" = "$3" ]; then - echo "OK: the $1 is $3" + echo "OK ๐Ÿ‘: the $1 is $3" else - echo "Fail: the $1 is $2, expected $3" + echo "Fail ๐Ÿ˜ž: the $1 is $2, expected $3" exit 1 fi } test-le() { if [ "$2" -le "$3" ]; then - echo "OK: the $1 of $2 is <= $3" + echo "OK ๐Ÿ‘: the $1 of $2 is <= $3" else - echo "Fail: the $1 is $2, expected <= $3" + echo "Fail ๐Ÿ˜ž: the $1 is $2, expected <= $3" exit 1 fi } diff --git a/.github/scripts/x-forwarded-headers.sh b/.github/scripts/x-forwarded-headers.sh index e72000147..8d22ea4d1 100755 --- a/.github/scripts/x-forwarded-headers.sh +++ b/.github/scripts/x-forwarded-headers.sh @@ -5,8 +5,8 @@ EXPECTED_SELF_LINK="$PROTO://blaze.de/fhir/Patient" ACTUAL_SELF_LINK=$(curl -s -H 'X-Forwarded-Host:blaze.de' -H "X-Forwarded-Proto:$PROTO" http://localhost:8080/fhir/Patient | jq -r .link[0].url | cut -d? -f1) if [ "$EXPECTED_SELF_LINK" = "$ACTUAL_SELF_LINK" ]; then - echo "Success" + echo "OK ๐Ÿ‘" else - echo "Fail: expected '$EXPECTED_SELF_LINK' but was '$ACTUAL_SELF_LINK'" + echo "Fail ๐Ÿ˜ž: expected '$EXPECTED_SELF_LINK' but was '$ACTUAL_SELF_LINK'" exit 1 fi diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9b6632cbc..632788b21 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -88,7 +88,7 @@ jobs: - name: Setup Clojure uses: DeLaGuardo/setup-clojure@master with: - cli: '1.11.1.1347' + cli: '1.11.1.1403' - name: Check out Git repository uses: actions/checkout@v3 @@ -118,7 +118,7 @@ jobs: - name: Setup Clojure uses: DeLaGuardo/setup-clojure@master with: - cli: '1.11.1.1347' + cli: '1.11.1.1403' - name: Check out Git repository uses: actions/checkout@v3 @@ -161,7 +161,7 @@ jobs: - name: Setup Clojure uses: DeLaGuardo/setup-clojure@master with: - cli: '1.11.1.1347' + cli: '1.11.1.1403' - name: Check out Git repository uses: actions/checkout@v3 @@ -189,7 +189,7 @@ jobs: - name: Setup Clojure uses: DeLaGuardo/setup-clojure@master with: - cli: '1.11.1.1347' + cli: '1.11.1.1403' - name: Check out Git repository uses: actions/checkout@v3 @@ -880,7 +880,7 @@ jobs: - name: Setup Clojure uses: DeLaGuardo/setup-clojure@master with: - cli: '1.11.1.1347' + cli: '1.11.1.1403' - name: Check out Git repository uses: actions/checkout@v3 @@ -1543,7 +1543,7 @@ jobs: - name: Setup Clojure uses: DeLaGuardo/setup-clojure@master with: - cli: '1.11.1.1347' + cli: '1.11.1.1403' - name: Check out Git repository uses: actions/checkout@v3 @@ -1755,7 +1755,7 @@ jobs: uses: actions/configure-pages@v3 - name: Upload artifact - uses: actions/upload-pages-artifact@v1 + uses: actions/upload-pages-artifact@v2 with: path: docs/.vitepress/dist diff --git a/CHANGELOG.md b/CHANGELOG.md index 19ff404b5..dd210ce5a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,17 @@ # Changelog +## v0.22.1 + +### Bugfixes + +* Resolve Relative Attachment.url Values Like References ([#804](https://github.com/samply/blaze/issues/804)) + +### Performance + +* Skip Indexing Unnecessary Compartment Values ([#1045](https://github.com/samply/blaze/pull/1045)) + +The full changelog can be found [here](https://github.com/samply/blaze/milestone/75?closed=1). + ## v0.22.0 It's not recommended to downgrade from this version to an older version because [#1041](https://github.com/samply/blaze/pull/1041) introduces a new transaction command called `keep` that would be ignored by older versions. However the transaction log is only read at the moment transactions happen or if the index is rebuild. So it will be ok to downgrade in emergency without rebuilding the index. diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index f9856a2c8..9de9ae0dd 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -32,6 +32,7 @@ In addition to the REPL development inside a single module, it's possible to run * rename every occurrence of the old version, say `0.13.0` into the new version, say `0.13.1` * rename every occurrence of old Docker images like `samply/blaze:0.13` into the new image, say `samply/blaze:0.14` * update the last changed date in `blaze.rest-api.capabilities` +* update the eclipse-temurin base image SHA in `Dockerfile` * update the CHANGELOG based on the milestone * create a commit with the title `Release v` * create a PR from the release branch into master diff --git a/Dockerfile b/Dockerfile index 28407aaf2..3813367c0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,5 @@ -FROM eclipse-temurin:17.0.7_7-jre-jammy +# Update the SHA by calling crane digest eclipse-temurin:17-jre-jammy +FROM eclipse-temurin:17-jre-jammy@sha256:6c78e6fb90509752eaf265b2b71df41199103332c86a38ddb06919108586fd7d RUN apt-get update && apt-get upgrade -y && \ apt-get install libjemalloc2 -y && \ @@ -7,7 +8,7 @@ RUN apt-get update && apt-get upgrade -y && \ rm -rf /var/lib/apt/lists/ RUN mkdir -p /app/data && chown 1001:1001 /app/data -COPY target/blaze-0.22.0-standalone.jar /app/ +COPY target/blaze-0.22.1-standalone.jar /app/ WORKDIR /app USER 1001 @@ -18,4 +19,4 @@ ENV INDEX_DB_DIR="/app/data/index" ENV TRANSACTION_DB_DIR="/app/data/transaction" ENV RESOURCE_DB_DIR="/app/data/resource" -CMD ["java", "-jar", "blaze-0.22.0-standalone.jar"] +CMD ["java", "-jar", "blaze-0.22.1-standalone.jar"] diff --git a/Makefile b/Makefile index 376281fc8..5fba06554 100644 --- a/Makefile +++ b/Makefile @@ -38,4 +38,7 @@ deps-tree: deps-list: clojure -X:deps list -.PHONY: $(MODULES) lint-root lint prep test-root test test-coverage clean-root clean build-frontend uberjar outdated deps-tree deps-list +cloc: clean + cloc --exclude-ext=iml,json,csv .github dev docs modules profiling scripts src test + +.PHONY: $(MODULES) lint-root lint prep test-root test test-coverage clean-root clean build-frontend uberjar outdated deps-tree deps-list cloc diff --git a/README.md b/README.md index de1a26eec..aae71092b 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ The goal of this project is to provide a FHIRยฎ Store with an internal CQL Evalu Blaze passes all [Touchstone FHIR 4.0.1 Basic Tests][12] and almost all [CQL Tests][3]. Please refer to the [Conformance](docs/conformance.md) section and report any issues you encounter during evaluation. -Latest release: [v0.22.0][5] +Latest release: [v0.22.1][5] ## Quick Start @@ -74,7 +74,7 @@ Unless required by applicable law or agreed to in writing, software distributed [3]: [4]: -[5]: +[5]: [6]: [7]: [8]: diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 000000000..747f7e4dc --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,10 @@ +# Security Policy + +## Supported Versions + +Only the most recent major version is regularly updated and receives security fixes. + +## Reporting a Vulnerability + +Please use the project's [private vulnerability reporting feature](https://github.com/samply/blaze/security/advisories) +to report any vulnerabilities. For more information, see diff --git a/build.clj b/build.clj index 1844f4eb6..1b008c346 100644 --- a/build.clj +++ b/build.clj @@ -2,7 +2,7 @@ (:require [clojure.tools.build.api :as b])) (def lib 'samply/blaze) -(def version "0.22.0") +(def version "0.22.1") (def class-dir "target/classes") (def basis (b/create-basis {:project "deps.edn"})) (def uber-file (format "target/%s-%s-standalone.jar" (name lib) version)) diff --git a/deps.edn b/deps.edn index 5724c8ade..d7f5c0a00 100644 --- a/deps.edn +++ b/deps.edn @@ -59,7 +59,7 @@ {:build {:deps {io.github.clojure/tools.build - {:git/tag "v0.9.4" :git/sha "76b78fe"}} + {:git/tag "v0.9.5" :git/sha "24f2894"}} :ns-default build} :test @@ -92,7 +92,7 @@ :outdated {:replace-deps {com.github.liquidz/antq - {:mvn/version "2.5.1095"} + {:mvn/version "2.5.1109"} org.slf4j/slf4j-nop {:mvn/version "2.0.7"}} diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts index 1fd9ae64f..616bb3c62 100644 --- a/docs/.vitepress/config.ts +++ b/docs/.vitepress/config.ts @@ -27,7 +27,7 @@ export default defineConfig({ nav: [ {text: 'Home', link: '/'}, { - text: "v0.22.0", + text: "v0.22.1", items: [ { text: 'Changelog', diff --git a/docs/deployment/docker-deployment.md b/docs/deployment/docker-deployment.md index e56eb3a54..a1a676ea1 100644 --- a/docs/deployment/docker-deployment.md +++ b/docs/deployment/docker-deployment.md @@ -27,7 +27,7 @@ Blaze should log something like this: 2023-06-09T08:30:30.126Z b45689460ff3 main INFO [blaze.core:67] - JVM version: 17.0.7 2023-06-09T08:30:30.126Z b45689460ff3 main INFO [blaze.core:68] - Maximum available memory: 1738 MiB 2023-06-09T08:30:30.126Z b45689460ff3 main INFO [blaze.core:69] - Number of available processors: 2 -2023-06-09T08:30:30.126Z b45689460ff3 main INFO [blaze.core:70] - Successfully started ๐Ÿ”ฅ Blaze version 0.22.0 in 9.0 seconds +2023-06-09T08:30:30.126Z b45689460ff3 main INFO [blaze.core:70] - Successfully started ๐Ÿ”ฅ Blaze version 0.22.1 in 9.0 seconds ``` In order to test connectivity, query the health endpoint: @@ -47,7 +47,7 @@ that should return: ```json { "name": "Blaze", - "version": "0.22.0" + "version": "0.22.1" } ``` diff --git a/docs/deployment/manual-deployment.md b/docs/deployment/manual-deployment.md index 591889fbd..99d56f71a 100644 --- a/docs/deployment/manual-deployment.md +++ b/docs/deployment/manual-deployment.md @@ -2,12 +2,12 @@ The installation works under Windows, Linux and macOS. The only dependency is an installed OpenJDK 11 or 17 with 17 recommended. Blaze is tested with [Eclipse Temurin][1]. -Blaze runs on the JVM and comes as single JAR file. Download the most recent version [here](https://github.com/samply/blaze/releases/tag/v0.22.0). Look for `blaze-0.22.0-standalone.jar`. +Blaze runs on the JVM and comes as single JAR file. Download the most recent version [here](https://github.com/samply/blaze/releases/tag/v0.22.1). Look for `blaze-0.22.1-standalone.jar`. After the download, you can start blaze with the following command (Linux, macOS): ```sh -java -jar blaze-0.22.0-standalone.jar +java -jar blaze-0.22.1-standalone.jar ``` Blaze will run with an in-memory, volatile database for testing and demo purposes. @@ -17,14 +17,14 @@ Blaze can be run with durable storage by setting the environment variables `STOR Under Linux/macOS: ```sh -STORAGE=standalone java -jar blaze-0.22.0-standalone.jar +STORAGE=standalone java -jar blaze-0.22.1-standalone.jar ``` Under Windows, you need to set the Environment variables in the PowerShell before starting Blaze: ```powershell $Env:STORAGE="standalone" -java -jar blaze-0.22.0-standalone.jar +java -jar blaze-0.22.1-standalone.jar ``` This will create three directories called `index`, `transaction` and `resource` inside the current working directory, one for each database part used. @@ -42,7 +42,7 @@ The output should look like this: 2021-06-27T11:02:37.834Z ee086ef908c1 main INFO [blaze.core:64] - JVM version: 16.0.2 2021-06-27T11:02:37.834Z ee086ef908c1 main INFO [blaze.core:65] - Maximum available memory: 1738 MiB 2021-06-27T11:02:37.835Z ee086ef908c1 main INFO [blaze.core:66] - Number of available processors: 8 -2021-06-27T11:02:37.836Z ee086ef908c1 main INFO [blaze.core:67] - Successfully started Blaze version 0.22.0 in 8.2 seconds +2021-06-27T11:02:37.836Z ee086ef908c1 main INFO [blaze.core:67] - Successfully started Blaze version 0.22.1 in 8.2 seconds ``` In order to test connectivity, query the health endpoint: @@ -62,7 +62,7 @@ that should return: ```json { "name": "Blaze", - "version": "0.22.0" + "version": "0.22.1" } ``` diff --git a/docs/performance/cql.md b/docs/performance/cql.md index 91d2b2928..b2926fb8a 100644 --- a/docs/performance/cql.md +++ b/docs/performance/cql.md @@ -6,7 +6,8 @@ The following systems were used for performance evaluation: | System | Provider | CPU | Cores | RAM | SSD | Heap Mem | Block Cache | Resource Cache ยน | |--------|----------|------------|------:|--------:|-------:|---------:|------------:|-----------------:| -| LE1080 | on-prem | EPYC 7543P | 16 | 128 GiB | 2 TB | 16 GiB | 32 GiB | 5 M | +| LEA47 | on-prem | EPYC 7543P | 16 | 128 GiB | 2 TB | 32 GiB | 16 GiB | 10 M | +| LEA58 | on-prem | EPYC 7543P | 32 | 256 GiB | 2 TB | 64 GiB | 32 GiB | 20 M | ยน Size of the resource cache (DB_RESOURCE_CACHE_SIZE) @@ -46,12 +47,15 @@ blazectl evaluate-measure "cql/observation-$CODE.yml" --server http://localhost: | System | Dataset | Code | # Hits | Time (s) | StdDev | Pat./s | |--------|---------|---------|-------:|---------:|-------:|--------:| -| LE1080 | 100k | 17861-6 | 2 k | 0.26 | 0.158 | 384.5 k | -| LE1080 | 100k | 8310-5 | 60 k | 0.28 | 0.142 | 351.4 k | -| LE1080 | 100k | 72514-3 | 100 k | 0.27 | 0.128 | 367.0 k | -| LE1080 | 1M | 17861-6 | 25 k | 2.61 | 0.208 | 383.1 k | -| LE1080 | 1M | 8310-5 | 603 k | 2.68 | 0.201 | 372.8 k | -| LE1080 | 1M | 72514-3 | 998 k | 2.82 | 0.192 | 354.9 k | +| LEA47 | 100k | 17861-6 | 2 k | 0.26 | 0.158 | 384.5 k | +| LEA47 | 100k | 8310-5 | 60 k | 0.28 | 0.142 | 351.4 k | +| LEA47 | 100k | 72514-3 | 100 k | 0.27 | 0.128 | 367.0 k | +| LEA47 | 1M | 17861-6 | 25 k | 2.61 | 0.208 | 383.1 k | +| LEA47 | 1M | 8310-5 | 603 k | 2.68 | 0.201 | 372.8 k | +| LEA47 | 1M | 72514-3 | 998 k | 2.82 | 0.192 | 354.9 k | +| LEA58 | 1M | 17861-6 | 25 k | 2.87 | 0.291 | 348.5 k | +| LEA58 | 1M | 8310-5 | 603 k | 3.02 | 0.257 | 330.8 k | +| LEA58 | 1M | 72514-3 | 998 k | 3.06 | 0.426 | 326.7 k | The evaluation of patient based measures doesn't depend on the number of hits (patients). The time needed to evaluate a CQL expression over all patients only depends on the total number of patients. The measurements show that Blaze can evaluate about 350 k Patients per second. @@ -81,9 +85,46 @@ blazectl evaluate-measure "cql/observation-$CODE-$VALUE.yml" --server http://loc | System | Dataset | Code | Value | # Hits | Time (s) | StdDev | Pat./s | |--------|---------|---------|--------:|-------:|---------:|-------:|--------:| -| LE1080 | 100k | 29463-7 | 13.6 kg | 10 k | 0.68 | 0.031 | 146.9 k | -| LE1080 | 100k | 29463-7 | 75.3 kg | 50 k | 0.51 | 0.033 | 197.1 k | -| LE1080 | 100k | 29463-7 | 185 kg | 100 k | 0.30 | 0.106 | 331.6 k | -| LE1080 | 1M | 29463-7 | 13.6 kg | 99 k | 151.05 | 4.674 | 6.6 k | -| LE1080 | 1M | 29463-7 | 75.3 kg | 500 k | 104.68 | 2.022 | 9.6 k | -| LE1080 | 1M | 29463-7 | 185 kg | 998 k | 3.19 | 0.176 | 313.8 k | +| LEA47 | 100k | 29463-7 | 13.6 kg | 10 k | 0.68 | 0.031 | 146.9 k | +| LEA47 | 100k | 29463-7 | 75.3 kg | 50 k | 0.51 | 0.033 | 197.1 k | +| LEA47 | 100k | 29463-7 | 185 kg | 100 k | 0.30 | 0.106 | 331.6 k | +| LEA47 | 1M | 29463-7 | 13.6 kg | 99 k | 151.05 | 4.674 | 6.6 k | +| LEA47 | 1M | 29463-7 | 75.3 kg | 500 k | 104.68 | 2.022 | 9.6 k | +| LEA47 | 1M | 29463-7 | 185 kg | 998 k | 3.19 | 0.176 | 313.8 k | +| LEA58 | 1M | 29463-7 | 13.6 kg | 99 k | 8.24 | 0.072 | 121.4 k | +| LEA58 | 1M | 29463-7 | 75.3 kg | 500 k | 6.59 | 0.140 | 151.8 k | +| LEA58 | 1M | 29463-7 | 185 kg | 998 k | 3.04 | 0.209 | 329.0 k | + +## Code and Value Search + +In this section, CQL Queries for selecting Patients which have Observation resources with code 718-7 (Hemoglobin), date between 2015 and 2019 and age of patient at observation date below 18. + +```text +library "hemoglobin-date-age" +using FHIR version '4.0.0' +include FHIRHelpers version '4.0.0' + +codesystem loinc: 'http://loinc.org' + +context Patient + +define InInitialPopulation: + exists [Observation: Code '718-7' from loinc] O + where year from O.effective between 2015 and 2019 + and AgeInYearsAt(O.effective) < 18 +``` + +The CQL query is executed with the following `blazectl` command: + +```sh +blazectl evaluate-measure "cql/hemoglobin-date-age.yml" --server http://localhost:8080/fhir | jq -rf cql/result.jq +``` + +| System | Dataset | Code | # Hits | Time (s) | StdDev | Pat./s | +|--------|---------|------------|-------:|---------:|-------:|--------:| +| LEA47 | 100k | hemoglobin | 20 k | 0.35 | 0.034 | 286.5 k | +| LEA47 | 100k | calcium | 20 k | 1.50 | 0.035 | 66.6 k | +| LEA47 | 1M | hemoglobin | 200 k | 4.79 | 0.119 | 208.8 k | +| LEA47 | 1M | calcium | 199 k | 182.90 | 3.900 | 5.5 k | +| LEA58 | 1M | hemoglobin | 200 k | 3.55 | 0.038 | 281.8 k | +| LEA58 | 1M | calcium | 199 k | 10.10 | 0.033 | 99.0 k | diff --git a/docs/performance/cql/calcium-date-age.cql b/docs/performance/cql/calcium-date-age.cql new file mode 100644 index 000000000..30fb87733 --- /dev/null +++ b/docs/performance/cql/calcium-date-age.cql @@ -0,0 +1,12 @@ +library "calcium-date-age" +using FHIR version '4.0.0' +include FHIRHelpers version '4.0.0' + +codesystem loinc: 'http://loinc.org' + +context Patient + +define InInitialPopulation: + exists [Observation: Code '49765-1' from loinc] O + where year from O.effective between 2015 and 2019 + and AgeInYearsAt(O.effective) < 59 diff --git a/docs/performance/cql/calcium-date-age.yml b/docs/performance/cql/calcium-date-age.yml new file mode 100644 index 000000000..75c9fff29 --- /dev/null +++ b/docs/performance/cql/calcium-date-age.yml @@ -0,0 +1,5 @@ +library: cql/calcium-date-age.cql +group: +- type: Patient + population: + - expression: InInitialPopulation diff --git a/docs/performance/cql/code-date-age-search.sh b/docs/performance/cql/code-date-age-search.sh new file mode 100755 index 000000000..0470f1017 --- /dev/null +++ b/docs/performance/cql/code-date-age-search.sh @@ -0,0 +1,22 @@ +#!/bin/bash -e + +SCRIPT_DIR="$(dirname "$(readlink -f "$0")")" +. "$SCRIPT_DIR/util.sh" + +BASE="http://localhost:8080/fhir" +START_EPOCH="$(date +"%s")" +PATIENT_TOTAL="$(curl -sH 'Accept: application/fhir+json' "$BASE/Patient?_summary=count" | jq -r .total)" +CODE="$1" + +echo "Counting Patients with Observations with code $CODE, date between 2015 and 2019 and age of patient at observation date below 18..." + +MEASURE_FILE="$SCRIPT_DIR/$CODE-date-age.yml" +TIMES_FILE="$START_EPOCH-$CODE-date-age.times" +COUNT="$(blazectl --server "$BASE" evaluate-measure "$MEASURE_FILE" 2> /dev/null | jq -r '.group[0].population[0].count')" + +for i in {0..6} +do + blazectl --server "$BASE" evaluate-measure "$MEASURE_FILE" 2> /dev/null |\ + jq -rf "$SCRIPT_DIR/duration.jq" >> "$TIMES_FILE" +done +calc-cql-print-stats "$TIMES_FILE" "$PATIENT_TOTAL" "$COUNT" diff --git a/docs/performance/cql/code-value-search.sh b/docs/performance/cql/code-value-search.sh index e6178ab95..2126191c3 100755 --- a/docs/performance/cql/code-value-search.sh +++ b/docs/performance/cql/code-value-search.sh @@ -6,19 +6,14 @@ SCRIPT_DIR="$(dirname "$(readlink -f "$0")")" BASE="http://localhost:8080/fhir" START_EPOCH="$(date +"%s")" PATIENT_TOTAL="$(curl -sH 'Accept: application/fhir+json' "$BASE/Patient?_summary=count" | jq -r .total)" +CODE="$1" +VALUE="$2" -for CODE in "body-weight" +echo "Counting Patients with Observations with code $CODE and value $VALUE..." +COUNT="$(blazectl --server "$BASE" evaluate-measure "$SCRIPT_DIR/observation-$CODE-$VALUE.yml" 2> /dev/null | jq -r '.group[0].population[0].count')" +for i in {0..6} do - for VALUE in "10" "50" "100" - do - echo "Counting Patients with Observations with code $CODE and value $VALUE..." - COUNT="$(blazectl --server "$BASE" evaluate-measure "$SCRIPT_DIR/observation-$CODE-$VALUE.yml" 2> /dev/null | jq -r '.group[0].population[0].count')" - for i in {0..21} - do - blazectl evaluate-measure "cql/observation-$CODE-$VALUE.yml" --server "$BASE" 2> /dev/null |\ - jq -rf cql/duration.jq >> "$START_EPOCH-$CODE-$VALUE.times" - done - - calc-cql-print-stats "$START_EPOCH-$CODE-$VALUE.times" "$PATIENT_TOTAL" "$COUNT" - done + blazectl evaluate-measure "cql/observation-$CODE-$VALUE.yml" --server "$BASE" 2> /dev/null |\ + jq -rf cql/duration.jq >> "$START_EPOCH-$CODE-$VALUE.times" done +calc-cql-print-stats "$START_EPOCH-$CODE-$VALUE.times" "$PATIENT_TOTAL" "$COUNT" diff --git a/docs/performance/cql/hemoglobin-date-age.cql b/docs/performance/cql/hemoglobin-date-age.cql new file mode 100644 index 000000000..81c25492a --- /dev/null +++ b/docs/performance/cql/hemoglobin-date-age.cql @@ -0,0 +1,12 @@ +library "hemoglobin-date-age" +using FHIR version '4.0.0' +include FHIRHelpers version '4.0.0' + +codesystem loinc: 'http://loinc.org' + +context Patient + +define InInitialPopulation: + exists [Observation: Code '718-7' from loinc] O + where year from O.effective between 2015 and 2019 + and AgeInYearsAt(O.effective) < 18 diff --git a/docs/performance/cql/hemoglobin-date-age.yml b/docs/performance/cql/hemoglobin-date-age.yml new file mode 100644 index 000000000..007292147 --- /dev/null +++ b/docs/performance/cql/hemoglobin-date-age.yml @@ -0,0 +1,5 @@ +library: cql/hemoglobin-date-age.cql +group: +- type: Patient + population: + - expression: InInitialPopulation diff --git a/docs/performance/cql/measures/calcium-years.cql b/docs/performance/cql/measures/calcium-years.cql new file mode 100644 index 000000000..7b0c09c8c --- /dev/null +++ b/docs/performance/cql/measures/calcium-years.cql @@ -0,0 +1,13 @@ +library "calcium-years" +using FHIR version '4.0.0' +include FHIRHelpers version '4.0.0' + +codesystem loinc: 'http://loinc.org' + +context Patient + +define Calcium: + [Observation: Code '49765-1' from loinc] + +define function ObsYear(obs FHIR.Observation): + year from obs.effective diff --git a/docs/performance/cql/measures/calcium-years.yml b/docs/performance/cql/measures/calcium-years.yml new file mode 100644 index 000000000..75fb9bd33 --- /dev/null +++ b/docs/performance/cql/measures/calcium-years.yml @@ -0,0 +1,8 @@ +library: cql/measures/calcium-years.cql +group: +- type: Observation + population: + - expression: Calcium + stratifier: + - code: year + expression: ObsYear diff --git a/docs/performance/cql/measures/condition-1.cql b/docs/performance/cql/measures/condition-1.cql deleted file mode 100644 index 89fffb8d4..000000000 --- a/docs/performance/cql/measures/condition-1.cql +++ /dev/null @@ -1,8 +0,0 @@ -library "gender-male" -using FHIR version '4.0.0' -include FHIRHelpers version '4.0.0' - -context Patient - -define InInitialPopulation: - Patient.gender = 'male' diff --git a/docs/performance/cql/measures/hemoglobin-years.cql b/docs/performance/cql/measures/hemoglobin-years.cql new file mode 100644 index 000000000..ddb5da9c6 --- /dev/null +++ b/docs/performance/cql/measures/hemoglobin-years.cql @@ -0,0 +1,13 @@ +library "hemoglobin-years" +using FHIR version '4.0.0' +include FHIRHelpers version '4.0.0' + +codesystem loinc: 'http://loinc.org' + +context Patient + +define Hemoglobin: + [Observation: Code '718-7' from loinc] + +define function ObsYear(obs FHIR.Observation): + year from obs.effective diff --git a/docs/performance/cql/measures/hemoglobin-years.yml b/docs/performance/cql/measures/hemoglobin-years.yml new file mode 100644 index 000000000..55bd7f298 --- /dev/null +++ b/docs/performance/cql/measures/hemoglobin-years.yml @@ -0,0 +1,8 @@ +library: cql/measures/hemoglobin-years.cql +group: +- type: Observation + population: + - expression: Hemoglobin + stratifier: + - code: year + expression: ObsYear diff --git a/docs/performance/cql/measures/years.jq b/docs/performance/cql/measures/years.jq new file mode 100644 index 000000000..c67daf780 --- /dev/null +++ b/docs/performance/cql/measures/years.jq @@ -0,0 +1,3 @@ +["year", "count"], +(.group[0].stratifier[0].stratum[] | [.value.text, .population[0].count]) +| @csv diff --git a/docs/performance/cql/simple-code-search.sh b/docs/performance/cql/simple-code-search.sh index 51c6cfa5d..e59cea0e6 100755 --- a/docs/performance/cql/simple-code-search.sh +++ b/docs/performance/cql/simple-code-search.sh @@ -6,16 +6,14 @@ SCRIPT_DIR="$(dirname "$(readlink -f "$0")")" BASE="http://localhost:8080/fhir" START_EPOCH="$(date +"%s")" PATIENT_TOTAL="$(curl -sH 'Accept: application/fhir+json' "$BASE/Patient?_summary=count" | jq -r .total)" +CODE="$1" -for CODE in "17861-6" "8310-5" "72514-3" +echo "Counting Patients with Observations with code $CODE..." +COUNT="$(blazectl --server "$BASE" evaluate-measure "$SCRIPT_DIR/observation-$CODE.yml" 2> /dev/null | jq -r '.group[0].population[0].count')" +for i in {0..6} do - echo "Counting Patients with Observations with code $CODE..." - COUNT="$(blazectl --server "$BASE" evaluate-measure "$SCRIPT_DIR/observation-$CODE.yml" 2> /dev/null | jq -r '.group[0].population[0].count')" - for i in {0..21} - do - blazectl --server "$BASE" evaluate-measure "$SCRIPT_DIR/observation-$CODE.yml" 2> /dev/null |\ - jq -rf "$SCRIPT_DIR/duration.jq" >> "$START_EPOCH-$CODE.times" - done - - calc-cql-print-stats "$START_EPOCH-$CODE.times" "$PATIENT_TOTAL" "$COUNT" + blazectl --server "$BASE" evaluate-measure "$SCRIPT_DIR/observation-$CODE.yml" 2> /dev/null |\ + jq -rf "$SCRIPT_DIR/duration.jq" >> "$START_EPOCH-$CODE.times" done + +calc-cql-print-stats "$START_EPOCH-$CODE.times" "$PATIENT_TOTAL" "$COUNT" diff --git a/docs/performance/cql/statistics/calcium-years.csv b/docs/performance/cql/statistics/calcium-years.csv new file mode 100644 index 000000000..35afa59d3 --- /dev/null +++ b/docs/performance/cql/statistics/calcium-years.csv @@ -0,0 +1,12 @@ +"year","count" +"2013",95759 +"2014",158209 +"2015",163570 +"2016",170303 +"2017",173554 +"2018",179375 +"2019",185083 +"2020",191134 +"2021",196930 +"2022",203073 +"2023",74269 diff --git a/docs/performance/cql/statistics/hemoglobin-years.csv b/docs/performance/cql/statistics/hemoglobin-years.csv new file mode 100644 index 000000000..eb1794ea9 --- /dev/null +++ b/docs/performance/cql/statistics/hemoglobin-years.csv @@ -0,0 +1,12 @@ +"year","count" +"2013",11856 +"2014",19781 +"2015",19854 +"2016",19587 +"2017",19768 +"2018",20176 +"2019",21191 +"2020",32589 +"2021",28666 +"2022",20979 +"2023",807 diff --git a/docs/performance/fhir-search.md b/docs/performance/fhir-search.md index 46afa3f76..4b928ddad 100644 --- a/docs/performance/fhir-search.md +++ b/docs/performance/fhir-search.md @@ -10,7 +10,7 @@ The following systems were used for performance evaluation: | System | Provider | CPU | Cores | RAM | SSD | Heap Mem | Block Cache | Resource Cache ยน | |--------|----------|------------|------:|--------:|-------:|---------:|------------:|-----------------:| -| LE1080 | on-prem | EPYC 7543P | 16 | 128 GiB | 2 TB | 32 GiB | 16 GiB | 11 M | +| LEA47 | on-prem | EPYC 7543P | 16 | 128 GiB | 2 TB | 32 GiB | 16 GiB | 11 M | | CCX42 | Hetzner | EPYC 7763 | 16 | 64 GiB | 360 GB | 16 GiB | 8 GiB | 5 M | ยน Size of the resource cache (DB_RESOURCE_CACHE_SIZE) @@ -40,15 +40,15 @@ curl -s "http://localhost:8080/fhir/Observation?code=http://loinc.org|$CODE&_sum | System | Dataset | Code | # Hits | Time (s) | StdDev | T/1M ยน | |--------|---------|---------|-------:|---------:|-------:|-------:| -| LE1080 | 100k | 8310-5 | 115 k | 0.06 | 0.002 | 0.53 ยฒ | -| LE1080 | 100k | 55758-7 | 1.0 M | 0.52 | 0.006 | 0.51 | -| LE1080 | 100k | 72514-3 | 2.7 M | 1.36 | 0.016 | 0.49 | +| LEA47 | 100k | 8310-5 | 115 k | 0.06 | 0.002 | 0.53 ยฒ | +| LEA47 | 100k | 55758-7 | 1.0 M | 0.52 | 0.006 | 0.51 | +| LEA47 | 100k | 72514-3 | 2.7 M | 1.36 | 0.016 | 0.49 | | CCX42 | 100k | 8310-5 | 115 k | 0.07 | 0.005 | 0.62 ยฒ | | CCX42 | 100k | 55758-7 | 1.0 M | 0.53 | 0.062 | 0.52 | | CCX42 | 100k | 72514-3 | 2.7 M | 1.31 | 0.017 | 0.47 | -| LE1080 | 1M | 8310-5 | 1.1 M | 0.59 | 0.008 | 0.50 | -| LE1080 | 1M | 55758-7 | 10.1 M | 5.46 | 0.097 | 0.53 | -| LE1080 | 1M | 72514-3 | 27.3 M | 14.60 | 0.077 | 0.53 | +| LEA47 | 1M | 8310-5 | 1.1 M | 0.59 | 0.008 | 0.50 | +| LEA47 | 1M | 55758-7 | 10.1 M | 5.46 | 0.097 | 0.53 | +| LEA47 | 1M | 72514-3 | 27.3 M | 14.60 | 0.077 | 0.53 | ยน time in seconds per 1 million resources, ยฒ Because the measurement of the duration includes the whole HTTP stack, durations of small results like the 115 k includes an overhead that results in a duration more like 0.6 seconds per 1 million hits. @@ -66,15 +66,15 @@ blazectl download --server http://localhost:8080/fhir Observation -q "code=http: | System | Dataset | Code | # Hits | Time (s) | StdDev | T/1M ยน | |--------|---------|---------|-------:|---------:|-------:|--------:| -| LE1080 | 100k | 8310-5 | 115 k | 1.91 | 0.025 | 16.58 | -| LE1080 | 100k | 55758-7 | 1.0 M | 15.85 | 0.224 | 15.73 | -| LE1080 | 100k | 72514-3 | 2.7 M | 42.12 | 0.591 | 15.32 | +| LEA47 | 100k | 8310-5 | 115 k | 1.91 | 0.025 | 16.58 | +| LEA47 | 100k | 55758-7 | 1.0 M | 15.85 | 0.224 | 15.73 | +| LEA47 | 100k | 72514-3 | 2.7 M | 42.12 | 0.591 | 15.32 | | CCX42 | 100k | 8310-5 | 115 k | 2.46 | 0.044 | 21.34 | | CCX42 | 100k | 55758-7 | 1.0 M | 19.74 | 0.237 | 19.60 | | CCX42 | 100k | 72514-3 | 2.7 M | 52.95 | 0.484 | 19.26 | -| LE1080 | 1M | 8310-5 | 1.1 M | 19.11 | 0.383 | 16.48 | -| LE1080 | 1M | 55758-7 | 10.1 M | 201.66 | 2.506 | 19.88 | -| LE1080 | 1M | 72514-3 | 27.3 M | 809.80 | 6.294 | 29.61 ยฒ | +| LEA47 | 1M | 8310-5 | 1.1 M | 19.11 | 0.383 | 16.48 | +| LEA47 | 1M | 55758-7 | 10.1 M | 201.66 | 2.506 | 19.88 | +| LEA47 | 1M | 72514-3 | 27.3 M | 809.80 | 6.294 | 29.61 ยฒ | ยน time in seconds per 1 million resources, ยฒ resource cache size (11 million) is smaller than the number of resources returned (27.3 million) @@ -94,15 +94,15 @@ blazectl download --server http://localhost:8080/fhir Observation -q "code=http: | System | Dataset | Code | # Hits | Time (s) | StdDev | T/1M ยน | |--------|---------|---------|-------:|---------:|-------:|--------:| -| LE1080 | 100k | 8310-5 | 115 k | 1.30 | 0.027 | 11.26 | -| LE1080 | 100k | 55758-7 | 1.0 M | 10.47 | 0.126 | 10.39 | -| LE1080 | 100k | 72514-3 | 2.7 M | 27.67 | 0.263 | 10.06 | +| LEA47 | 100k | 8310-5 | 115 k | 1.30 | 0.027 | 11.26 | +| LEA47 | 100k | 55758-7 | 1.0 M | 10.47 | 0.126 | 10.39 | +| LEA47 | 100k | 72514-3 | 2.7 M | 27.67 | 0.263 | 10.06 | | CCX42 | 100k | 8310-5 | 115 k | 1.78 | 0.052 | 15.41 | | CCX42 | 100k | 55758-7 | 1.0 M | 14.46 | 0.177 | 14.35 | | CCX42 | 100k | 72514-3 | 2.7 M | 37.82 | 0.107 | 13.76 | -| LE1080 | 1M | 8310-5 | 1.1 M | 12.38 | 0.136 | 10.68 | -| LE1080 | 1M | 55758-7 | 10.1 M | 143.98 | 1.816 | 14.19 | -| LE1080 | 1M | 72514-3 | 27.3 M | 617.21 | 5.668 | 22.57 ยฒ | +| LEA47 | 1M | 8310-5 | 1.1 M | 12.38 | 0.136 | 10.68 | +| LEA47 | 1M | 55758-7 | 10.1 M | 143.98 | 1.816 | 14.19 | +| LEA47 | 1M | 72514-3 | 27.3 M | 617.21 | 5.668 | 22.57 ยฒ | ยน time in seconds per 1 million resources, ยฒ resource cache size (11 million) is smaller than the number of resources returned (27.3 million) @@ -122,15 +122,15 @@ curl -s "http://localhost:8080/fhir/Observation?code=http://loinc.org|$CODE&valu | System | Dataset | Code | Value | # Hits | Time (s) | StdDev | T/1M ยน | |--------|---------|---------|------:|-------:|---------:|-------:|-------:| -| LE1080 | 100k | 29463-7 | 26.8 | -| LE1080 | 100k | 29463-7 | 79.5 | -| LE1080 | 100k | 29463-7 | 183 | +| LEA47 | 100k | 29463-7 | 26.8 | +| LEA47 | 100k | 29463-7 | 79.5 | +| LEA47 | 100k | 29463-7 | 183 | | CCX42 | 100k | 29463-7 | 26.8 | 158 k | 56.45 | 0.149 | 357.08 | | CCX42 | 100k | 29463-7 | 79.5 | 790 k | 56.72 | 0.174 | 71.84 | | CCX42 | 100k | 29463-7 | 183 | 1.6 M | 56.77 | 0.135 | 35.87 | -| LE1080 | 1M | 29463-7 | 26.8 | -| LE1080 | 1M | 29463-7 | 79.5 | -| LE1080 | 1M | 29463-7 | 183 | +| LEA47 | 1M | 29463-7 | 26.8 | +| LEA47 | 1M | 29463-7 | 79.5 | +| LEA47 | 1M | 29463-7 | 183 | ยน time in seconds per 1 million resources @@ -148,15 +148,15 @@ blazectl download --server http://localhost:8080/fhir Observation -q "code=http: | System | Dataset | Code | Value | # Hits | Time (s) | StdDev | T/1M ยน | |--------|---------|---------|------:|-------:|---------:|-------:|-------:| -| LE1080 | 100k | 29463-7 | 26.8 | -| LE1080 | 100k | 29463-7 | 79.5 | -| LE1080 | 100k | 29463-7 | 183 | +| LEA47 | 100k | 29463-7 | 26.8 | +| LEA47 | 100k | 29463-7 | 79.5 | +| LEA47 | 100k | 29463-7 | 183 | | CCX42 | 100k | 29463-7 | 26.8 | 158 k | 59.19 | 0.060 | 374.44 | | CCX42 | 100k | 29463-7 | 79.5 | 790 k | 70.26 | 0.142 | 88.98 | | CCX42 | 100k | 29463-7 | 183 | 1.6 M | 83.82 | 0.076 | 52.97 | -| LE1080 | 1M | 29463-7 | 26.8 | -| LE1080 | 1M | 29463-7 | 79.5 | -| LE1080 | 1M | 29463-7 | 183 | +| LEA47 | 1M | 29463-7 | 26.8 | +| LEA47 | 1M | 29463-7 | 79.5 | +| LEA47 | 1M | 29463-7 | 183 | ยน time in seconds per 1 million resources @@ -174,15 +174,15 @@ blazectl download --server http://localhost:8080/fhir Observation -q "code=http: | System | Dataset | Code | Value | # Hits | Time (s) | StdDev | T/1M ยน | |--------|---------|---------|------:|-------:|---------:|-------:|-------:| -| LE1080 | 100k | 29463-7 | 26.8 | -| LE1080 | 100k | 29463-7 | 79.5 | -| LE1080 | 100k | 29463-7 | 183 | +| LEA47 | 100k | 29463-7 | 26.8 | +| LEA47 | 100k | 29463-7 | 79.5 | +| LEA47 | 100k | 29463-7 | 183 | | CCX42 | 100k | 29463-7 | 26.8 | 158 k | 58.07 | 0.028 | 367.36 | | CCX42 | 100k | 29463-7 | 79.5 | 790 k | 65.31 | 0.197 | 82.71 | | CCX42 | 100k | 29463-7 | 183 | 1.6 M | 74.40 | 0.183 | 47.01 | -| LE1080 | 1M | 29463-7 | 26.8 | -| LE1080 | 1M | 29463-7 | 79.5 | -| LE1080 | 1M | 29463-7 | 183 | +| LEA47 | 1M | 29463-7 | 26.8 | +| LEA47 | 1M | 29463-7 | 79.5 | +| LEA47 | 1M | 29463-7 | 183 | ยน time in seconds per 1 million resources @@ -239,12 +239,12 @@ curl -s "http://localhost:8080/fhir/Observation?date=$YEAR&_summary=count" | System | Dataset | Year | # Hits | Time (s) | StdDev | T/1M ยน | |--------|---------|------|-------:|---------:|-------:|-------:| -| LE1080 | 100k | 2013 | 3.1 M | 2.32 | 0.044 | 0.74 | -| LE1080 | 100k | 2019 | 6.0 M | 4.31 | 0.087 | 0.72 | +| LEA47 | 100k | 2013 | 3.1 M | 2.32 | 0.044 | 0.74 | +| LEA47 | 100k | 2019 | 6.0 M | 4.31 | 0.087 | 0.72 | | CCX42 | 100k | 2013 | 3.1 M | 2.00 | 0.028 | 0.63 | | CCX42 | 100k | 2019 | 6.0 M | 3.91 | 0.142 | 0.65 | -| LE1080 | 1M | 2013 | 31.1 M | 21.49 | 0.328 | 0.69 | -| LE1080 | 1M | 2019 | 60.0 M | 44.07 | 1.014 | 0.73 | +| LEA47 | 1M | 2013 | 31.1 M | 21.49 | 0.328 | 0.69 | +| LEA47 | 1M | 2019 | 60.0 M | 44.07 | 1.014 | 0.73 | ยน time in seconds per 1 million resources @@ -260,12 +260,12 @@ blazectl download --server http://localhost:8080/fhir Observation -q "date=$YEAR | System | Dataset | Year | # Hits | Time (s) | StdDev | T/1M ยน | |--------|---------|------|-------:|---------:|-------:|--------:| -| LE1080 | 100k | 2013 | 3.1 M | 63.11 | 0.564 | 20.19 | -| LE1080 | 100k | 2019 | 6.0 M | 124.12 | 2.017 | 20.76 | +| LEA47 | 100k | 2013 | 3.1 M | 63.11 | 0.564 | 20.19 | +| LEA47 | 100k | 2019 | 6.0 M | 124.12 | 2.017 | 20.76 | | CCX42 | 100k | 2013 | 3.1 M | 128.16 | 0.406 | 41.00 | | CCX42 | 100k | 2019 | 6.0 M | 276.13 | 2.020 | 46.18 ยฒ | -| LE1080 | 1M | 2013 | 31.1 M | 938.28 | 12.990 | 30.19 ยฒ | -| LE1080 | 1M | 2019 | 60.0 M | 2306.56 | 7.608 | 38.40 ยฒ | +| LEA47 | 1M | 2013 | 31.1 M | 938.28 | 12.990 | 30.19 ยฒ | +| LEA47 | 1M | 2019 | 60.0 M | 2306.56 | 7.608 | 38.40 ยฒ | ยน time in seconds per 1 million resources, ยฒ resource cache size is smaller than the number of resources returned @@ -283,12 +283,12 @@ blazectl download --server http://localhost:8080/fhir Observation -q "date=$YEAR | System | Dataset | Year | # Hits | Time (s) | StdDev | T/1M ยน | |--------|---------|------|-------:|---------:|-------:|--------:| -| LE1080 | 100k | 2013 | 3.1 M | 41.90 | 0.150 | 13.40 | -| LE1080 | 100k | 2019 | 6.0 M | 81.32 | 0.454 | 13.60 | +| LEA47 | 100k | 2013 | 3.1 M | 41.90 | 0.150 | 13.40 | +| LEA47 | 100k | 2019 | 6.0 M | 81.32 | 0.454 | 13.60 | | CCX42 | 100k | 2013 | 3.1 M | 85.59 | 0.293 | 27.38 | | CCX42 | 100k | 2019 | 6.0 M | 179.29 | 1.786 | 29.99 ยฒ | -| LE1080 | 1M | 2013 | 31.1 M | 615.23 | 7.651 | 19.80 ยฒ | -| LE1080 | 1M | 2019 | 60.0 M | 1792.99 | 6.333 | 29.85 ยฒ | +| LEA47 | 1M | 2013 | 31.1 M | 615.23 | 7.651 | 19.80 ยฒ | +| LEA47 | 1M | 2019 | 60.0 M | 1792.99 | 6.333 | 29.85 ยฒ | ยน time in seconds per 1 million resources, ยฒ resource cache size is smaller than the number of resources returned diff --git a/modules/admin-api/.clj-kondo/config.edn b/modules/admin-api/.clj-kondo/config.edn index a9c7992de..b588017ea 100644 --- a/modules/admin-api/.clj-kondo/config.edn +++ b/modules/admin-api/.clj-kondo/config.edn @@ -22,6 +22,7 @@ {blaze.async.comp ac blaze.db.kv.rocksdb rocksdb clojure.spec.alpha s + cognitect.anomalies anom integrant.core ig ring.util.response ring taoensso.timbre log}}} diff --git a/modules/admin-api/Makefile b/modules/admin-api/Makefile index 8eb60f27a..7510b665c 100644 --- a/modules/admin-api/Makefile +++ b/modules/admin-api/Makefile @@ -10,7 +10,13 @@ test: prep test-coverage: prep clojure -M:test:coverage +deps-tree: + clojure -X:deps tree + +deps-list: + clojure -X:deps list + clean: rm -rf .clj-kondo/.cache .cpcache target -.PHONY: lint prep test test-coverage clean +.PHONY: lint prep test test-coverage deps-tree deps-list clean diff --git a/modules/admin-api/deps.edn b/modules/admin-api/deps.edn index 15247f11e..e20aadb66 100644 --- a/modules/admin-api/deps.edn +++ b/modules/admin-api/deps.edn @@ -19,8 +19,8 @@ {:extra-paths ["test"] :extra-deps - {blaze/test-util - {:local/root "../test-util"}}} + {blaze/module-test-util + {:local/root "../module-test-util"}}} :kaocha {:extra-deps diff --git a/modules/admin-api/test/blaze/admin_api_test.clj b/modules/admin-api/test/blaze/admin_api_test.clj index e3e96bc25..f538d8207 100644 --- a/modules/admin-api/test/blaze/admin_api_test.clj +++ b/modules/admin-api/test/blaze/admin_api_test.clj @@ -2,7 +2,8 @@ (:require [blaze.admin-api] [blaze.db.kv.rocksdb.protocols :as p] - [blaze.test-util :as tu :refer [given-thrown with-system]] + [blaze.module.test-util :refer [with-system]] + [blaze.test-util :as tu :refer [given-thrown]] [clojure.spec.alpha :as s] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [deftest testing]] diff --git a/modules/anomaly/Makefile b/modules/anomaly/Makefile index 8eb60f27a..196a53ceb 100644 --- a/modules/anomaly/Makefile +++ b/modules/anomaly/Makefile @@ -1,16 +1,13 @@ lint: clj-kondo --lint src test deps.edn -prep: - clojure -X:deps prep - -test: prep +test: clojure -M:test:kaocha --profile :ci -test-coverage: prep +test-coverage: clojure -M:test:coverage clean: rm -rf .clj-kondo/.cache .cpcache target -.PHONY: lint prep test test-coverage clean +.PHONY: lint test test-coverage clean diff --git a/modules/anomaly/deps.edn b/modules/anomaly/deps.edn index 8e1ccfb58..66ce96ced 100644 --- a/modules/anomaly/deps.edn +++ b/modules/anomaly/deps.edn @@ -1,14 +1,12 @@ {:deps - { - ;; TODO: only needed for prepping - blaze/fhir-structure - {:local/root "../fhir-structure"} - - blaze/spec + {blaze/spec {:local/root "../spec"} com.cognitect/anomalies - {:mvn/version "0.1.12"}} + {:mvn/version "0.1.12"} + + io.aviso/pretty + {:mvn/version "1.4.4"}} :aliases {:test diff --git a/modules/async/.clj-kondo/config.edn b/modules/async/.clj-kondo/config.edn index 07ef93f1d..354f88a6c 100644 --- a/modules/async/.clj-kondo/config.edn +++ b/modules/async/.clj-kondo/config.edn @@ -15,6 +15,10 @@ {:level :warning} :warn-on-reflection - {:level :warning :warn-only-on-interop true}} + {:level :warning :warn-only-on-interop true} + + :consistent-alias + {:aliases + {cognitect.anomalies anom}}} :skip-comments true} diff --git a/modules/async/Makefile b/modules/async/Makefile index 8eb60f27a..196a53ceb 100644 --- a/modules/async/Makefile +++ b/modules/async/Makefile @@ -1,16 +1,13 @@ lint: clj-kondo --lint src test deps.edn -prep: - clojure -X:deps prep - -test: prep +test: clojure -M:test:kaocha --profile :ci -test-coverage: prep +test-coverage: clojure -M:test:coverage clean: rm -rf .clj-kondo/.cache .cpcache target -.PHONY: lint prep test test-coverage clean +.PHONY: lint test test-coverage clean diff --git a/modules/async/deps.edn b/modules/async/deps.edn index cc0732045..3a1c78ea7 100644 --- a/modules/async/deps.edn +++ b/modules/async/deps.edn @@ -5,10 +5,6 @@ blaze/executor {:local/root "../executor"} - ;; TODO: only needed for prepping - blaze/fhir-structure - {:local/root "../fhir-structure"} - com.taoensso/timbre {:mvn/version "5.2.1"}} diff --git a/modules/async/test/blaze/async/comp_test.clj b/modules/async/test/blaze/async/comp_test.clj index 2730dc591..3e06c4969 100644 --- a/modules/async/test/blaze/async/comp_test.clj +++ b/modules/async/test/blaze/async/comp_test.clj @@ -4,10 +4,11 @@ [blaze.async.comp :as ac :refer [do-sync]] [blaze.async.comp-spec] [blaze.executors :as ex] - [blaze.test-util :as tu :refer [given-failed-future]] + [blaze.test-util :as tu] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [deftest is testing]] - [cognitect.anomalies :as anom]) + [cognitect.anomalies :as anom] + [juxt.iota :refer [given]]) (:import [java.util.concurrent TimeUnit])) @@ -19,6 +20,11 @@ (test/use-fixtures :each tu/fixture) +(defmacro given-failed-future [future & body] + `(given (try (deref ~future) (is false) (catch Exception e# (ba/anomaly e#))) + ~@body)) + + (deftest completed-future-test (testing "on completed future" (is (= ::x @(ac/completed-future ::x)))) diff --git a/modules/byte-buffer/Makefile b/modules/byte-buffer/Makefile index 61db6c022..362333b11 100644 --- a/modules/byte-buffer/Makefile +++ b/modules/byte-buffer/Makefile @@ -1,10 +1,7 @@ lint: clj-kondo --lint src test deps.edn -prep: - clojure -X:deps prep - -test: prep +test: clojure -M:test:kaocha --profile :ci test-coverage: @@ -13,4 +10,4 @@ test-coverage: clean: rm -rf .clj-kondo/.cache .cpcache target -.PHONY: lint prep test test-coverage clean +.PHONY: lint test test-coverage clean diff --git a/modules/byte-buffer/deps.edn b/modules/byte-buffer/deps.edn index 65160548a..bb68cff07 100644 --- a/modules/byte-buffer/deps.edn +++ b/modules/byte-buffer/deps.edn @@ -1,11 +1,6 @@ {:deps - { - ;; TODO: only needed for prepping - blaze/fhir-structure - {:local/root "../fhir-structure"} - - com.google.protobuf/protobuf-java - {:mvn/version "3.23.3"}} + {com.google.protobuf/protobuf-java + {:mvn/version "3.24.1"}} :aliases {:test diff --git a/modules/byte-string/deps.edn b/modules/byte-string/deps.edn index c72cc6625..51b1e3e78 100644 --- a/modules/byte-string/deps.edn +++ b/modules/byte-string/deps.edn @@ -2,7 +2,7 @@ :deps {com.google.guava/guava - {:mvn/version "32.1.0-jre" + {:mvn/version "32.1.2-jre" :exclusions [com.google.code.findbugs/jsr305 org.checkerframework/checker-qual @@ -10,7 +10,7 @@ com.google.j2objc/j2objc-annotations]} com.google.protobuf/protobuf-java - {:mvn/version "3.23.3"} + {:mvn/version "3.24.1"} com.fasterxml.jackson.core/jackson-databind {:mvn/version "2.15.2"}}} diff --git a/modules/cassandra/.clj-kondo/config.edn b/modules/cassandra/.clj-kondo/config.edn index e3b746ad7..97e80c930 100644 --- a/modules/cassandra/.clj-kondo/config.edn +++ b/modules/cassandra/.clj-kondo/config.edn @@ -12,6 +12,10 @@ {:level :warning} :warn-on-reflection - {:level :warning :warn-only-on-interop true}} + {:level :warning :warn-only-on-interop true} + + :consistent-alias + {:aliases + {cognitect.anomalies anom}}} :skip-comments true} diff --git a/modules/cassandra/Makefile b/modules/cassandra/Makefile index 8eb60f27a..196a53ceb 100644 --- a/modules/cassandra/Makefile +++ b/modules/cassandra/Makefile @@ -1,16 +1,13 @@ lint: clj-kondo --lint src test deps.edn -prep: - clojure -X:deps prep - -test: prep +test: clojure -M:test:kaocha --profile :ci -test-coverage: prep +test-coverage: clojure -M:test:coverage clean: rm -rf .clj-kondo/.cache .cpcache target -.PHONY: lint prep test test-coverage clean +.PHONY: lint test test-coverage clean diff --git a/modules/cassandra/deps.edn b/modules/cassandra/deps.edn index ab9689adf..cc9feb932 100644 --- a/modules/cassandra/deps.edn +++ b/modules/cassandra/deps.edn @@ -3,7 +3,7 @@ {:local/root "../async"} com.datastax.oss/java-driver-core - {:mvn/version "4.16.0"} + {:mvn/version "4.17.0"} ;; current version of transitive dependency of com.datastax.oss/java-driver-core com.fasterxml.jackson.core/jackson-databind @@ -11,18 +11,18 @@ ;; current version of transitive dependency of com.datastax.oss/java-driver-core io.netty/netty-handler - {:mvn/version "4.1.94.Final"}} + {:mvn/version "4.1.96.Final"}} :aliases {:test {:extra-paths ["test"] :extra-deps - {blaze/test-util - {:local/root "../test-util"} + {blaze/byte-buffer + {:local/root "../byte-buffer"} - org.clojars.akiel/iota - {:mvn/version "0.1"}}} + blaze/test-util + {:local/root "../test-util"}}} :kaocha {:extra-deps diff --git a/modules/coll/Makefile b/modules/coll/Makefile index 8eb60f27a..196a53ceb 100644 --- a/modules/coll/Makefile +++ b/modules/coll/Makefile @@ -1,16 +1,13 @@ lint: clj-kondo --lint src test deps.edn -prep: - clojure -X:deps prep - -test: prep +test: clojure -M:test:kaocha --profile :ci -test-coverage: prep +test-coverage: clojure -M:test:coverage clean: rm -rf .clj-kondo/.cache .cpcache target -.PHONY: lint prep test test-coverage clean +.PHONY: lint test test-coverage clean diff --git a/modules/coll/deps.edn b/modules/coll/deps.edn index f12db7563..f8a58805d 100644 --- a/modules/coll/deps.edn +++ b/modules/coll/deps.edn @@ -1,10 +1,4 @@ -{:deps - { - ;; TODO: only needed for prepping - blaze/fhir-structure - {:local/root "../fhir-structure"}} - - :aliases +{:aliases {:test {:extra-paths ["test"] diff --git a/modules/cql/.clj-kondo/config.edn b/modules/cql/.clj-kondo/config.edn index 096ecf455..7172e6ab1 100644 --- a/modules/cql/.clj-kondo/config.edn +++ b/modules/cql/.clj-kondo/config.edn @@ -2,7 +2,7 @@ {blaze.anomaly/if-ok clojure.core/let blaze.anomaly/when-ok clojure.core/let blaze.db.api-stub/with-system-data clojure.core/with-open - blaze.test-util/with-system clojure.core/with-open + blaze.module.test-util/with-system clojure.core/with-open blaze.elm.compiler.macros/defunop clojure.core/defn blaze.elm.compiler.macros/defbinop clojure.core/defn blaze.elm.compiler.macros/defternop clojure.core/defn @@ -40,7 +40,11 @@ {:aliases {blaze.anomaly ba blaze.coll.core coll + blaze.cql-translator t blaze.db.api d + blaze.elm.compiler c + blaze.elm.compiler.external-data ed + blaze.elm.expression expr cognitect.anomalies anom clojure.java.io io clojure.spec.alpha s diff --git a/modules/cql/deps.edn b/modules/cql/deps.edn index ab4251897..55df91cec 100644 --- a/modules/cql/deps.edn +++ b/modules/cql/deps.edn @@ -11,17 +11,17 @@ {:mvn/version "2.15.2"} info.cqframework/cql-to-elm - {:mvn/version "2.10.0" + {:mvn/version "2.11.0" :exclusions [xpp3/xpp3_xpath]} info.cqframework/elm-jackson - {:mvn/version "2.10.0"} + {:mvn/version "2.11.0"} info.cqframework/model-jackson - {:mvn/version "2.10.0"} + {:mvn/version "2.11.0"} info.cqframework/quick - {:mvn/version "2.10.0"} + {:mvn/version "2.11.0"} org.apache.commons/commons-text {:mvn/version "1.10.0"} diff --git a/modules/cql/src/blaze/cql_translator_spec.clj b/modules/cql/src/blaze/cql_translator_spec.clj index 30546b3c5..63a0cdf48 100644 --- a/modules/cql/src/blaze/cql_translator_spec.clj +++ b/modules/cql/src/blaze/cql_translator_spec.clj @@ -1,12 +1,12 @@ (ns blaze.cql-translator-spec (:require [blaze.anomaly-spec] - [blaze.cql-translator :as cql-translator] + [blaze.cql-translator :as t] [blaze.elm.spec] [clojure.spec.alpha :as s] [cognitect.anomalies :as anom])) -(s/fdef cql-translator/translate +(s/fdef t/translate :args (s/cat :cql string?) :ret (s/or :library :elm/library :anomaly ::anom/anomaly)) diff --git a/modules/cql/src/blaze/elm/code.clj b/modules/cql/src/blaze/elm/code.clj index 15ac0b9e0..bce654696 100644 --- a/modules/cql/src/blaze/elm/code.clj +++ b/modules/cql/src/blaze/elm/code.clj @@ -1,6 +1,7 @@ (ns blaze.elm.code "Implementation of the code type." (:require + [blaze.elm.compiler.core :as core] [blaze.elm.concept :as concept] [blaze.elm.protocols :as p])) @@ -21,7 +22,15 @@ p/Descendents (descendents [_] - [code nil system version])) + [code nil system version]) + + core/Expression + (-static [_] + true) + (-eval [this _ _ _] + this) + (-form [_] + `(~'code ~system ~version ~code))) (defn to-code diff --git a/modules/cql/src/blaze/elm/compiler/arithmetic_operators.clj b/modules/cql/src/blaze/elm/compiler/arithmetic_operators.clj index ee9dc7197..7fd8a573e 100644 --- a/modules/cql/src/blaze/elm/compiler/arithmetic_operators.clj +++ b/modules/cql/src/blaze/elm/compiler/arithmetic_operators.clj @@ -43,11 +43,17 @@ (p/floor x)) +;; TODO: 16.7. HighBoundary + + ;; 16.8. Log (defbinop log [x base] (p/log x base)) +;; TODO: 16.9. LowBoundary + + ;; 16.10. Ln (defunop ln [x] (p/ln x)) @@ -123,6 +129,9 @@ (p/power x exp)) +;; TODO: 16.17. Precision + + ;; 16.18. Predecessor (defunop predecessor [x] (p/predecessor x)) @@ -136,6 +145,8 @@ (if (and (core/static? operand) (core/static? precision)) (p/round operand precision) (reify core/Expression + (-static [_] + false) (-eval [_ context resource scope] (p/round (core/-eval operand context resource scope) (core/-eval precision context resource scope))) diff --git a/modules/cql/src/blaze/elm/compiler/clinical_operators.clj b/modules/cql/src/blaze/elm/compiler/clinical_operators.clj index b1c77f43c..49f5f031a 100644 --- a/modules/cql/src/blaze/elm/compiler/clinical_operators.clj +++ b/modules/cql/src/blaze/elm/compiler/clinical_operators.clj @@ -20,6 +20,8 @@ (when-let [date (core/compile* context date)] (let [chrono-precision (some-> precision core/to-chrono-unit)] (reify core/Expression + (-static [_] + false) (-eval [_ context resource scope] (p/duration-between (core/-eval birth-date context resource scope) diff --git a/modules/cql/src/blaze/elm/compiler/conditional_operators.clj b/modules/cql/src/blaze/elm/compiler/conditional_operators.clj index 89d53e456..7b2ccc72b 100644 --- a/modules/cql/src/blaze/elm/compiler/conditional_operators.clj +++ b/modules/cql/src/blaze/elm/compiler/conditional_operators.clj @@ -9,47 +9,49 @@ ;; 15.1. Case -(defrecord ComparandCaseExpression [comparand items else] - core/Expression - (-eval [_ context resource scope] - (let [comparand (core/-eval comparand context resource scope)] - (loop [[{:keys [when then]} & next-items] items] - (if (p/equal comparand (core/-eval when context resource scope)) - (core/-eval then context resource scope) - (if (empty? next-items) - (core/-eval else context resource scope) - (recur next-items))))))) - - -(defrecord MultiConditionalCaseExpression [items else] - core/Expression - (-eval [_ context resource scope] - (loop [[{:keys [when then]} & next-items] items] - (if (core/-eval when context resource scope) - (core/-eval then context resource scope) - (if (empty? next-items) - (core/-eval else context resource scope) - (recur next-items)))))) - - (defmethod core/compile* :elm.compiler.type/case [context {:keys [comparand else] items :caseItem}] (let [comparand (some->> comparand (core/compile* context)) items - (mapv + (map (fn [{:keys [when then]}] - {:when (core/compile* context when) - :then (core/compile* context then)}) + [(core/compile* context when) + (core/compile* context then)]) items) else (core/compile* context else)] (if comparand - (->ComparandCaseExpression comparand items else) - (->MultiConditionalCaseExpression items else)))) + (reify core/Expression + (-static [_] + false) + (-eval [_ context resource scope] + (let [comparand (core/-eval comparand context resource scope)] + (loop [[[when then] & next-items] items] + (if (p/equal comparand (core/-eval when context resource scope)) + (core/-eval then context resource scope) + (if (empty? next-items) + (core/-eval else context resource scope) + (recur next-items)))))) + (-form [_] + `(~'case ~(core/-form comparand) ~@(map core/-form (flatten items)) ~else))) + (reify core/Expression + (-static [_] + false) + (-eval [_ context resource scope] + (loop [[[when then] & next-items] items] + (if (core/-eval when context resource scope) + (core/-eval then context resource scope) + (if (empty? next-items) + (core/-eval else context resource scope) + (recur next-items))))) + (-form [_] + `(~'case ~@(map core/-form (flatten items)) ~else)))))) ;; 15.2. If (defrecord IfExpression [condition then else] core/Expression + (-static [_] + false) (-eval [_ context resource scope] (if (core/-eval condition context resource scope) (core/-eval then context resource scope) diff --git a/modules/cql/src/blaze/elm/compiler/core.clj b/modules/cql/src/blaze/elm/compiler/core.clj index db21cf4b9..813200722 100644 --- a/modules/cql/src/blaze/elm/compiler/core.clj +++ b/modules/cql/src/blaze/elm/compiler/core.clj @@ -12,6 +12,7 @@ (defprotocol Expression + (-static [expression]) (-eval [expression context resource scope] "Evaluates `expression` on `resource` using `context` and optional `scope` for scoped expressions inside queries.") @@ -24,12 +25,16 @@ (extend-protocol Expression nil + (-static [_] + true) (-eval [expr _ _ _] expr) (-form [_] 'nil) Object + (-static [_] + true) (-eval [expr _ _ _] expr) (-form [expr] @@ -37,7 +42,7 @@ (defn static? [x] - (not (instance? blaze.elm.compiler.core.Expression x))) + (-static x)) (defmulti compile* diff --git a/modules/cql/src/blaze/elm/compiler/date_time_operators.clj b/modules/cql/src/blaze/elm/compiler/date_time_operators.clj index 04dc5fc61..be0c08f03 100644 --- a/modules/cql/src/blaze/elm/compiler/date_time_operators.clj +++ b/modules/cql/src/blaze/elm/compiler/date_time_operators.clj @@ -28,64 +28,6 @@ (.toLocalDateTime))) -(defrecord YearExpression [year] - system/SystemType - (-type [_] :system/date) - core/Expression - (-eval [_ context resource scope] - (some-> (core/-eval year context resource scope) system/date))) - - -(defrecord DateTimeYearExpression [year] - core/Expression - (-eval [_ context resource scope] - (some-> (core/-eval year context resource scope) system/date-time))) - - -(defrecord YearMonthExpression [year month] - system/SystemType - (-type [_] :system/date) - core/Expression - (-eval [_ context resource scope] - (when-let [year (core/-eval year context resource scope)] - (if-let [month (core/-eval month context resource scope)] - (system/date year month) - (system/date year))))) - - -(defrecord DateTimeYearMonthExpression [year month] - core/Expression - (-eval [_ context resource scope] - (when-let [year (core/-eval year context resource scope)] - (if-let [month (core/-eval month context resource scope)] - (system/date-time year month) - (system/date-time year))))) - - -(defrecord LocalDateExpression [year month day] - system/SystemType - (-type [_] :system/date) - core/Expression - (-eval [_ context resource scope] - (when-let [year (core/-eval year context resource scope)] - (if-let [month (core/-eval month context resource scope)] - (if-let [day (core/-eval day context resource scope)] - (system/date year month day) - (system/date year month)) - (system/date year))))) - - -(defrecord DateTimeYearMonthDayExpression [year month day] - core/Expression - (-eval [_ context resource scope] - (when-let [year (core/-eval year context resource scope)] - (if-let [month (core/-eval month context resource scope)] - (if-let [day (core/-eval day context resource scope)] - (system/date-time year month day) - (system/date-time year month)) - (system/date-time year))))) - - ;; 18.6. Date (defmethod core/compile* :elm.compiler.type/date [context {:keys [year month day]}] @@ -97,19 +39,55 @@ (system/date year month day) (some? day) - (->LocalDateExpression year month day) + (reify + system/SystemType + (-type [_] :system/date) + core/Expression + (-static [_] + false) + (-eval [_ context resource scope] + (when-let [year (core/-eval year context resource scope)] + (if-let [month (core/-eval month context resource scope)] + (if-let [day (core/-eval day context resource scope)] + (system/date year month day) + (system/date year month)) + (system/date year)))) + (-form [_] + (list 'date (core/-form year) (core/-form month) (core/-form day)))) (and (int? month) (int? year)) (system/date year month) (some? month) - (->YearMonthExpression year month) + (reify + system/SystemType + (-type [_] :system/date) + core/Expression + (-static [_] + false) + (-eval [_ context resource scope] + (when-let [year (core/-eval year context resource scope)] + (if-let [month (core/-eval month context resource scope)] + (system/date year month) + (system/date year)))) + (-form [_] + (list 'date (core/-form year) (core/-form month)))) (int? year) (system/date year) :else - (some-> year ->YearExpression)))) + (when year + (reify + system/SystemType + (-type [_] :system/date) + core/Expression + (-static [_] + false) + (-eval [_ context resource scope] + (some-> (core/-eval year context resource scope) system/date)) + (-form [_] + (list 'date (core/-form year)))))))) ;; 18.7. DateFrom @@ -136,12 +114,21 @@ (and (int? millisecond) (int? second) (int? minute) (int? hour) (int? day) (int? month) (int? year)) (reify core/Expression + (-static [_] + false) (-eval [_ {:keys [now]} _ _] (to-local-date-time-with-offset - now year month day hour minute second millisecond timezone-offset))) + now year month day hour minute second millisecond timezone-offset)) + (-form [_] + (list 'date-time (core/-form year) (core/-form month) + (core/-form day) (core/-form hour) (core/-form minute) + (core/-form second) (core/-form millisecond) + (core/-form timezone-offset)))) (some? hour) (reify core/Expression + (-static [_] + false) (-eval [_ {:keys [now] :as context} resource scope] (to-local-date-time-with-offset now @@ -152,7 +139,12 @@ (or (core/-eval minute context resource scope) 0) (or (core/-eval second context resource scope) 0) (or (core/-eval millisecond context resource scope) 0) - timezone-offset))) + timezone-offset)) + (-form [_] + (list 'date-time (core/-form year) (core/-form month) + (core/-form day) (core/-form hour) (core/-form minute) + (core/-form second) (core/-form millisecond) + (core/-form timezone-offset)))) :else (throw (ex-info "Need at least an hour if timezone offset is given." @@ -161,6 +153,8 @@ (some? timezone-offset) (if (some? hour) (reify core/Expression + (-static [_] + false) (-eval [_ {:keys [now] :as context} resource scope] (to-local-date-time-with-offset now @@ -171,7 +165,12 @@ (or (core/-eval minute context resource scope) 0) (or (core/-eval second context resource scope) 0) (or (core/-eval millisecond context resource scope) 0) - (core/-eval timezone-offset context resource scope)))) + (core/-eval timezone-offset context resource scope))) + (-form [_] + (list 'date-time (core/-form year) (core/-form month) + (core/-form day) (core/-form hour) (core/-form minute) + (core/-form second) (core/-form millisecond) + (core/-form timezone-offset)))) (throw (ex-info "Need at least an hour if timezone offset is given." {:expression expression}))) @@ -183,6 +182,8 @@ (some? hour) (reify core/Expression + (-static [_] + false) (-eval [_ context resource scope] (system/date-time (core/-eval year context resource scope) @@ -191,25 +192,57 @@ (core/-eval hour context resource scope) (or (core/-eval minute context resource scope) 0) (or (core/-eval second context resource scope) 0) - (or (core/-eval millisecond context resource scope) 0)))) + (or (core/-eval millisecond context resource scope) 0))) + (-form [_] + (list 'date-time (core/-form year) (core/-form month) + (core/-form day) (core/-form hour) (core/-form minute) + (core/-form second) (core/-form millisecond)))) (and (int? day) (int? month) (int? year)) (system/date-time year month day) (some? day) - (->DateTimeYearMonthDayExpression year month day) + (reify core/Expression + (-static [_] + false) + (-eval [_ context resource scope] + (when-let [year (core/-eval year context resource scope)] + (if-let [month (core/-eval month context resource scope)] + (if-let [day (core/-eval day context resource scope)] + (system/date-time year month day) + (system/date-time year month)) + (system/date-time year)))) + (-form [_] + (list 'date-time (core/-form year) (core/-form month) + (core/-form day)))) (and (int? month) (int? year)) (system/date-time year month) (some? month) - (->DateTimeYearMonthExpression year month) + (reify core/Expression + (-static [_] + false) + (-eval [_ context resource scope] + (when-let [year (core/-eval year context resource scope)] + (if-let [month (core/-eval month context resource scope)] + (system/date-time year month) + (system/date-time year)))) + (-form [_] + (list 'date-time (core/-form year) (core/-form month)))) (int? year) (system/date-time year) :else - (some-> year ->DateTimeYearExpression))))) + (when year + (reify core/Expression + (-static [_] + false) + (-eval [_ context resource scope] + (some-> (core/-eval year context resource scope) system/date-time)) + (-form [_] + (list 'date-time (core/-form year))))))))) ;; 18.9. DateTimeComponentFrom @@ -230,6 +263,8 @@ ;; 18.13. Now (defrecord NowExpression [] core/Expression + (-static [_] + false) (-eval [_ {:keys [now]} _ _] now)) @@ -269,48 +304,66 @@ (some? millisecond) (reify core/Expression + (-static [_] + false) (-eval [_ context resource scope] (date-time/local-time (core/-eval hour context resource scope) (core/-eval minute context resource scope) (core/-eval second context resource scope) - (core/-eval millisecond context resource scope)))) + (core/-eval millisecond context resource scope))) + (-form [_] + (list 'time (core/-form hour) (core/-form minute) (core/-form second) + (core/-form millisecond)))) (and (int? second) (int? minute) (int? hour)) (date-time/local-time hour minute second) (some? second) (reify core/Expression + (-static [_] + false) (-eval [_ context resource scope] (date-time/local-time (core/-eval hour context resource scope) (core/-eval minute context resource scope) - (core/-eval second context resource scope)))) + (core/-eval second context resource scope))) + (-form [_] + (list 'time (core/-form hour) (core/-form minute) (core/-form second)))) (and (int? minute) (int? hour)) (date-time/local-time hour minute) (some? minute) (reify core/Expression + (-static [_] + false) (-eval [_ context resource scope] (date-time/local-time (core/-eval hour context resource scope) - (core/-eval minute context resource scope)))) + (core/-eval minute context resource scope))) + (-form [_] + (list 'time (core/-form hour) (core/-form minute)))) (int? hour) (date-time/local-time hour) :else (reify core/Expression + (-static [_] + false) (-eval [_ context resource scope] - (date-time/local-time (core/-eval hour context resource scope))))))) - - -(defrecord TimeOfDayExpression [] - core/Expression - (-eval [_ {:keys [now]} _ _] - (.toLocalTime ^OffsetDateTime now))) + (date-time/local-time (core/-eval hour context resource scope))) + (-form [_] + (list 'time (core/-form hour))))))) (def ^:private time-of-day-expr - (->TimeOfDayExpression)) + (reify + core/Expression + (-static [_] + false) + (-eval [_ {:keys [now]} _ _] + (.toLocalTime ^OffsetDateTime now)) + (-form [_] + 'time-of-day))) ;; 18.21. TimeOfDay @@ -321,6 +374,8 @@ (def ^:private today-expr (reify core/Expression + (-static [_] + false) (-eval [_ {:keys [now]} _ _] (DateDate/fromLocalDate (.toLocalDate ^OffsetDateTime now))) (-form [_] diff --git a/modules/cql/src/blaze/elm/compiler/external_data.clj b/modules/cql/src/blaze/elm/compiler/external_data.clj index 4148dcc99..2daf1fd0f 100644 --- a/modules/cql/src/blaze/elm/compiler/external_data.clj +++ b/modules/cql/src/blaze/elm/compiler/external_data.clj @@ -5,34 +5,55 @@ https://cql.hl7.org/04-logicalspecification.html." (:require [blaze.anomaly :as ba :refer [if-ok]] + [blaze.coll.core :as coll] [blaze.db.api :as d] + [blaze.db.impl.index.resource-handle :as rh] [blaze.elm.compiler.core :as core] [blaze.elm.compiler.structured-values] [blaze.elm.spec] [blaze.elm.util :as elm-util] + [blaze.fhir.spec.type.protocols :as p] [clojure.string :as str]) (:import [blaze.elm.compiler.structured_values SourcePropertyExpression] + [clojure.lang ILookup] [java.util List])) (set! *warn-on-reflection* true) -(defrecord CompartmentListRetrieveExpression [context data-type] - core/Expression - (-eval [_ {:keys [db]} {:keys [id]} _] - (d/list-compartment-resource-handles db context id data-type)) - (-form [_] - `(~'compartment-list-retrieve ~data-type))) +;; A resource that is a wrapper of a resource-handle that will lazily pull the +;; resource content if some property other than :id is accessed. +(deftype Resource [db handle content] + p/FhirType + (-type [_] + (p/-type handle)) + ILookup + (valAt [r key] + (.valAt r key nil)) + (valAt [_ key not-found] + (case key + :id (rh/id handle) + (-> (or @content (vreset! content @(d/pull-content db handle))) + (get key not-found)))) + + Object + (toString [_] + (.toString handle))) + + +(defn resource? [x] + (instance? Resource x)) -(defrecord CompartmentQueryRetrieveExpression [query data-type clauses] - core/Expression - (-eval [_ {:keys [db]} {:keys [id]} _] - (d/execute-query db query id)) - (-form [_] - `(~'compartment-query-retrieve ~data-type ~clauses))) + +(defn mk-resource [db handle] + (Resource. db handle (volatile! nil))) + + +(defn resource-mapper [db] + (map (partial mk-resource db))) (defn- code->clause-value [{:keys [system code]}] @@ -67,7 +88,13 @@ [node context data-type property codes] (let [clauses (-to-clauses codes property) query (d/compile-compartment-query node context data-type clauses)] - (->CompartmentQueryRetrieveExpression query data-type clauses))) + (reify core/Expression + (-static [_] + false) + (-eval [_ {:keys [db]} {:keys [id]} _] + (coll/eduction (resource-mapper db) (d/execute-query db query id))) + (-form [_] + `(~'retrieve ~data-type ~(d/query-clauses query)))))) (defn- split-reference [s] @@ -75,23 +102,21 @@ [(subs s 0 idx) (subs s (inc idx))])) -(defn- pull [db x] - (if (d/resource-handle? x) - @(d/pull-content db x) - x)) - - ;; TODO: find a better solution than hard coding this case (defrecord SpecimenPatientExpression [] core/Expression - (-eval [_ {:keys [db]} resource-or-handle _] - (let [{{:keys [reference]} :subject} (pull db resource-or-handle)] + (-static [_] + false) + (-eval [_ {:keys [db]} resource _] + (let [{{:keys [reference]} :subject} resource] (when reference (when-let [[type id] (split-reference reference)] (when (and (= "Patient" type) (string? id)) (let [{:keys [op] :as handle} (d/resource-handle db "Patient" id)] (when-not (identical? :delete op) - [@(d/pull-content db handle)])))))))) + [(mk-resource db handle)]))))))) + (-form [_] + '(retrieve (Specimen) "Patient"))) (def ^:private specimen-patient-expr @@ -107,55 +132,51 @@ (case data-type "Patient" specimen-patient-expr) - (->CompartmentListRetrieveExpression context data-type))) - - -(defrecord ResourceRetrieveExpression [] - core/Expression - (-eval [_ _ resource _] - [resource]) - (-form [_] - (list 'retrieve-resource))) + (reify core/Expression + (-static [_] + false) + (-eval [_ {:keys [db]} {:keys [id]} _] + (coll/eduction + (resource-mapper db) + (d/list-compartment-resource-handles db context id data-type))) + (-form [_] + `(~'retrieve ~data-type))))) (def ^:private resource-expr - (->ResourceRetrieveExpression)) + (reify core/Expression + (-static [_] + false) + (-eval [_ _ resource _] + [resource]) + (-form [_] + '(retrieve-resource)))) -(defrecord WithRelatedContextRetrieveExpression - [related-context-expr data-type] - core/Expression - (-eval [_ context resource scope] - (when-let [context-resource (core/-eval related-context-expr context resource scope)] - (core/-eval - (context-expr (-> context-resource :fhir/type name) data-type) - context - context-resource - scope)))) +(defn- unsupported-type-ns-anom [value-type-ns] + (ba/unsupported (format "Unsupported related context retrieve expression with result type namespace of `%s`." value-type-ns))) -(defrecord WithRelatedContextQueryRetrieveExpression - [context-expr query] - core/Expression - (-eval [_ {:keys [db] :as context} resource scope] - (when-let [{:keys [id]} (core/-eval context-expr context resource scope)] - (when (string? id) - (d/execute-query db query id))))) +(def ^:private unsupported-related-context-expr-without-type-anom + (ba/unsupported "Unsupported related context retrieve expression without result type.")) -(defrecord WithRelatedContextCodeRetrieveExpression - [context-expr data-type clauses] - core/Expression - (-eval [_ {:keys [db] :as context} resource scope] - (when-let [{:fhir/keys [type] :keys [id]} - (core/-eval context-expr context resource scope)] - (when-let [type (some-> type name)] - (when id - (ba/throw-when - (d/compartment-query db type id data-type clauses))))))) +(defn- related-context-expr-without-codes [related-context-expr data-type] + (reify core/Expression + (-static [_] + false) + (-eval [_ context resource scope] + (when-let [context-resource (core/-eval related-context-expr context resource scope)] + (core/-eval + (context-expr (-> context-resource :fhir/type name) data-type) + context + context-resource + scope))) + (-form [_] + (list 'retrieve (core/-form related-context-expr) data-type)))) -(defn related-context-expr +(defn- related-context-expr [node context-expr data-type code-property codes] (if (seq codes) (if-let [result-type-name (:result-type-name (meta context-expr))] @@ -163,30 +184,41 @@ (if (= "http://hl7.org/fhir" value-type-ns) (let [clauses [(into [code-property] (map code->clause-value) codes)]] (if-ok [query (d/compile-compartment-query node context-type data-type clauses)] - (->WithRelatedContextQueryRetrieveExpression context-expr query) + (reify core/Expression + (-static [_] + false) + (-eval [_ {:keys [db] :as context} resource scope] + (when-let [{:keys [id]} (core/-eval context-expr context resource scope)] + (when (string? id) + (coll/eduction + (resource-mapper db) + (d/execute-query db query id))))) + (-form [_] + (list 'retrieve (core/-form context-expr) data-type (d/query-clauses query)))) ba/throw-anom)) - - (->WithRelatedContextCodeRetrieveExpression - context-expr data-type - [(cons code-property (map code->clause-value codes))]))) - (->WithRelatedContextCodeRetrieveExpression - context-expr data-type - [(cons code-property (map code->clause-value codes))])) - (->WithRelatedContextRetrieveExpression context-expr data-type))) + (ba/throw-anom (unsupported-type-ns-anom value-type-ns)))) + (ba/throw-anom unsupported-related-context-expr-without-type-anom)) + (related-context-expr-without-codes context-expr data-type))) (defn- unfiltered-context-expr [node data-type code-property codes] (if (empty? codes) (reify core/Expression + (-static [_] + false) (-eval [_ {:keys [db]} _ _] - (vec (d/type-list db data-type))) + (coll/eduction (resource-mapper db) (d/type-list db data-type))) (-form [_] `(~'retrieve ~data-type))) (let [clauses [(into [code-property] (map code->clause-value) codes)]] (if-ok [query (d/compile-type-query node data-type clauses)] (reify core/Expression + (-static [_] + false) (-eval [_ {:keys [db]} _ _] - (vec (d/execute-query db query)))) + (coll/eduction (resource-mapper db) (d/execute-query db query))) + (-form [_] + `(~'retrieve ~data-type ~(d/query-clauses query)))) ba/throw-anom)))) diff --git a/modules/cql/src/blaze/elm/compiler/external_data_spec.clj b/modules/cql/src/blaze/elm/compiler/external_data_spec.clj new file mode 100644 index 000000000..c213f8de3 --- /dev/null +++ b/modules/cql/src/blaze/elm/compiler/external_data_spec.clj @@ -0,0 +1,19 @@ +(ns blaze.elm.compiler.external-data-spec + (:require + [blaze.db.spec] + [blaze.elm.compiler.external-data :as ed] + [clojure.spec.alpha :as s])) + + +(s/fdef ed/resource? + :args (s/cat :x any?) + :ret boolean?) + + +(s/fdef ed/mk-resource + :args (s/cat :db :blaze.db/db :handle :blaze.db/resource-handle) + :ret ed/resource?) + + +(s/fdef ed/resource-mapper + :args (s/cat :db :blaze.db/db)) diff --git a/modules/cql/src/blaze/elm/compiler/function.clj b/modules/cql/src/blaze/elm/compiler/function.clj index ece770ad5..e9cefd97c 100644 --- a/modules/cql/src/blaze/elm/compiler/function.clj +++ b/modules/cql/src/blaze/elm/compiler/function.clj @@ -5,6 +5,8 @@ (defn arity-n [name fn-expr operand-names operands] (reify core/Expression + (-static [_] + false) (-eval [_ context resource scope] (let [values (map #(core/-eval % context resource scope) operands)] (core/-eval fn-expr context resource (merge scope (zipmap operand-names values))))) diff --git a/modules/cql/src/blaze/elm/compiler/interval_operators.clj b/modules/cql/src/blaze/elm/compiler/interval_operators.clj index c680697cc..2aa313a7f 100644 --- a/modules/cql/src/blaze/elm/compiler/interval_operators.clj +++ b/modules/cql/src/blaze/elm/compiler/interval_operators.clj @@ -22,6 +22,8 @@ [type low high low-closed-expression high-closed-expression low-closed high-closed] core/Expression + (-static [_] + false) (-eval [_ context resource scope] (let [low (core/-eval low context resource scope) high (core/-eval high context resource scope) diff --git a/modules/cql/src/blaze/elm/compiler/library.clj b/modules/cql/src/blaze/elm/compiler/library.clj index d5d6b9022..966e98024 100644 --- a/modules/cql/src/blaze/elm/compiler/library.clj +++ b/modules/cql/src/blaze/elm/compiler/library.clj @@ -1,7 +1,7 @@ (ns blaze.elm.compiler.library (:require [blaze.anomaly :as ba :refer [if-ok when-ok]] - [blaze.elm.compiler :as compiler] + [blaze.elm.compiler :as c] [blaze.elm.compiler.function :as function] [blaze.elm.deps-infer :as deps-infer] [blaze.elm.equiv-relationships :as equiv-relationships] @@ -15,7 +15,7 @@ anomaly on errors." [context def] (let [context (assoc context :eval-context (:context def))] - (-> (ba/try-anomaly (update def :expression (partial compiler/compile context))) + (-> (ba/try-anomaly (update def :expression (partial c/compile context))) (ba/exceptionally #(assoc % :context context :elm/expression (:expression def)))))) @@ -64,7 +64,7 @@ [context {:keys [default] :as parameter-def}] (if (some? default) (-> (ba/try-anomaly - (assoc parameter-def :default (compiler/compile context default))) + (assoc parameter-def :default (c/compile context default))) (ba/exceptionally #(assoc % :context context :elm/expression default))) parameter-def)) diff --git a/modules/cql/src/blaze/elm/compiler/library_spec.clj b/modules/cql/src/blaze/elm/compiler/library_spec.clj index 70a6f8636..5ad47d211 100644 --- a/modules/cql/src/blaze/elm/compiler/library_spec.clj +++ b/modules/cql/src/blaze/elm/compiler/library_spec.clj @@ -1,7 +1,7 @@ (ns blaze.elm.compiler.library-spec (:require [blaze.anomaly-spec] - [blaze.elm.compiler :as-alias compiler] + [blaze.elm.compiler :as-alias c] [blaze.elm.compiler-spec] [blaze.elm.compiler.core :as core] [blaze.elm.compiler.expression-def :as-alias expression-def] @@ -20,22 +20,22 @@ :fhir.resource/type) -(s/def ::compiler/expression-def - (s/keys :req-un [::expression-def/name ::expression-def/context ::compiler/expression])) +(s/def ::c/expression-def + (s/keys :req-un [::expression-def/name ::expression-def/context ::c/expression])) -(s/def ::compiler/expression-defs +(s/def ::c/expression-defs (s/map-of :elm/name core/expr?)) -(s/def ::compiler/parameter-default-values - (s/map-of :elm/name ::compiler/expression)) +(s/def ::c/parameter-default-values + (s/map-of :elm/name ::c/expression)) -(s/def ::compiler/library - (s/keys :req-un [::compiler/expression-defs ::compiler/parameter-default-values])) +(s/def ::c/library + (s/keys :req-un [::c/expression-defs ::c/parameter-default-values])) (s/fdef library/compile-library :args (s/cat :node :blaze.db/node :library :elm/library :opts map?) - :ret (s/or :library ::compiler/library :anomaly ::anom/anomaly)) + :ret (s/or :library ::c/library :anomaly ::anom/anomaly)) diff --git a/modules/cql/src/blaze/elm/compiler/list_operators.clj b/modules/cql/src/blaze/elm/compiler/list_operators.clj index 6a633d36e..2f0c00c74 100644 --- a/modules/cql/src/blaze/elm/compiler/list_operators.clj +++ b/modules/cql/src/blaze/elm/compiler/list_operators.clj @@ -15,19 +15,22 @@ [clojure.lang ExceptionInfo])) -;; 20.1. List -(defrecord ListOperatorExpression [elements] - core/Expression - (-eval [_ context resource scope] - (mapv #(core/-eval % context resource scope) elements))) +(set! *warn-on-reflection* true) +;; 20.1. List (defmethod core/compile* :elm.compiler.type/list [context {elements :element}] (let [elements (mapv #(core/compile* context %) elements)] (if (every? core/static? elements) elements - (->ListOperatorExpression elements)))) + (reify core/Expression + (-static [_] + false) + (-eval [_ context resource scope] + (mapv #(core/-eval % context resource scope) elements)) + (-form [_] + `(~'list ~@(map core/-form elements))))))) ;; 20.3. Current @@ -35,11 +38,19 @@ [_ {:keys [scope]}] (if scope (reify core/Expression + (-static [_] + false) (-eval [_ _ _ scopes] - (get scopes scope))) + (get scopes scope)) + (-form [_] + (list 'current scope))) (reify core/Expression + (-static [_] + false) (-eval [_ _ _ scope] - scope)))) + scope) + (-form [_] + 'current)))) ;; 20.4. Distinct @@ -70,36 +81,41 @@ condition (core/compile* context condition)] (if scope (reify core/Expression + (-static [_] + false) (-eval [_ context resource scopes] (when-let [source (core/-eval source context resource scopes)] (filterv (fn [x] (core/-eval condition context resource (assoc scopes scope x))) - source)))) + source))) + (-form [_] + (list 'filter (core/-form source) (core/-form condition) scope))) (reify core/Expression + (-static [_] + false) (-eval [_ context resource scopes] (when-let [source (core/-eval source context resource scopes)] - (filterv - (fn [_] - (core/-eval condition context resource scopes)) - source))))))) + (filterv (partial core/-eval condition context resource) source))) + (-form [_] + (list 'filter (core/-form source) (core/-form condition))))))) ;; 20.10. First ;; ;; TODO: orderBy -(defrecord FirstExpression [source] - core/Expression - (-eval [_ context resource scopes] - (coll/first (core/-eval source context resource scopes)))) - - (defmethod core/compile* :elm.compiler.type/first [context {:keys [source]}] (let [source (core/compile* (assoc context :optimizations #{:first :non-distinct}) source)] (if (core/static? source) (first source) - (->FirstExpression source)))) + (reify core/Expression + (-static [_] + false) + (-eval [_ context resource scopes] + (coll/first (core/-eval source context resource scopes))) + (-form [_] + (list 'first (core/-form source))))))) ;; 20.11. Flatten @@ -123,19 +139,24 @@ element (core/compile* context element)] (if scope (reify core/Expression + (-static [_] + false) (-eval [_ context resource scopes] (when-let [source (core/-eval source context resource scopes)] (mapv (fn [x] (core/-eval element context resource (assoc scopes scope x))) - source)))) + source))) + (-form [_] + (list 'for-each (core/-form source) (core/-form element) scope))) (reify core/Expression + (-static [_] + false) (-eval [_ context resource scopes] (when-let [source (core/-eval source context resource scopes)] - (mapv - (fn [_] - (core/-eval element context resource scopes)) - source))))))) + (mapv (partial core/-eval element context resource) source))) + (-form [_] + (list 'for-each (core/-form source) (core/-form element))))))) ;; 20.16. IndexOf @@ -144,6 +165,8 @@ (let [source (core/compile* context source) element (core/compile* context element)] (reify core/Expression + (-static [_] + false) (-eval [_ context resource scopes] (when-let [source (core/-eval source context resource scopes)] (when-let [element (core/-eval element context resource scopes)] @@ -155,7 +178,9 @@ (p/equal element x) idx)) source)) - -1))))))) + -1)))) + (-form [_] + (list 'index-of (core/-form source) (core/-form element)))))) ;; 20.18. Last @@ -164,9 +189,15 @@ (defmethod core/compile* :elm.compiler.type/last [context {:keys [source]}] (let [source (core/compile* context source)] - (reify core/Expression - (-eval [_ context resource scopes] - (peek (core/-eval source context resource scopes)))))) + (if (core/static? source) + (peek source) + (reify core/Expression + (-static [_] + false) + (-eval [_ context resource scopes] + (peek (core/-eval source context resource scopes))) + (-form [_] + (list 'last (core/-form source))))))) ;; 20.24. Repeat @@ -188,23 +219,20 @@ (defmethod core/compile* :elm.compiler.type/slice [context {:keys [source] start-index :startIndex end-index :endIndex}] (let [source (core/compile* context source) - start-index (some->> start-index (core/compile* context)) - end-index (some->> end-index (core/compile* context))] + start-index (core/compile* context start-index) + end-index (core/compile* context end-index)] (reify core/Expression + (-static [_] + false) (-eval [_ context resource scopes] (when-let [source (core/-eval source context resource scopes)] (let [start-index (or (core/-eval start-index context resource scopes) 0) end-index (or (core/-eval end-index context resource scopes) (count source))] (if (or (neg? start-index) (< end-index start-index)) [] - (subvec source start-index end-index)))))))) - - -(defrecord SortByDirectionExpression [source comp] - core/Expression - (-eval [_ context resource scopes] - (when-let [source (core/-eval source context resource scopes)] - (sort-by identity comp source)))) + (subvec source start-index end-index))))) + (-form [_] + (list 'slice (core/-form source) (core/-form start-index) (core/-form end-index)))))) ;; 20.27. Sort @@ -217,7 +245,15 @@ (fn [source {:keys [type direction]}] (case type "ByDirection" - (->SortByDirectionExpression source (queries/comparator direction)))) + (let [comp (queries/comparator direction)] + (reify core/Expression + (-static [_] + false) + (-eval [_ context resource scopes] + (when-let [source (core/-eval source context resource scopes)] + (sort-by identity comp source))) + (-form [_] + (list 'sort (core/-form source) (keyword direction))))))) source sort-by-items))) diff --git a/modules/cql/src/blaze/elm/compiler/logical_operators.clj b/modules/cql/src/blaze/elm/compiler/logical_operators.clj index b19361ee6..1d0829ba4 100644 --- a/modules/cql/src/blaze/elm/compiler/logical_operators.clj +++ b/modules/cql/src/blaze/elm/compiler/logical_operators.clj @@ -11,6 +11,8 @@ ;; 13.1. And (defn- nil-and-expr [x] (reify core/Expression + (-static [_] + false) (-eval [_ context resource scope] (when (false? (core/-eval x context resource scope)) false)) @@ -37,6 +39,8 @@ false false nil (nil-and-expr a) (reify core/Expression + (-static [_] + false) (-eval [_ context resource scope] (let [a (core/-eval a context resource scope)] (if (false? a) @@ -74,6 +78,8 @@ ;; 13.4. Or (defn- nil-or-expr [x] (reify core/Expression + (-static [_] + false) (-eval [_ context resource scope] (when (true? (core/-eval x context resource scope)) true)) @@ -100,6 +106,8 @@ false a nil (nil-or-expr a) (reify core/Expression + (-static [_] + false) (-eval [_ context resource scope] (let [a (core/-eval a context resource scope)] (if (true? a) @@ -130,6 +138,8 @@ (condp identical? b true (reify core/Expression + (-static [_] + false) (-eval [_ context resource scope] (let [a (core/-eval a context resource scope)] (when (some? a) @@ -139,6 +149,8 @@ false a nil nil (reify core/Expression + (-static [_] + false) (-eval [_ context resource scope] (when-some [a (core/-eval a context resource scope)] (when-some [b (core/-eval b context resource scope)] diff --git a/modules/cql/src/blaze/elm/compiler/macros.clj b/modules/cql/src/blaze/elm/compiler/macros.clj index 9bbfa40d6..617bccd24 100644 --- a/modules/cql/src/blaze/elm/compiler/macros.clj +++ b/modules/cql/src/blaze/elm/compiler/macros.clj @@ -1,45 +1,57 @@ (ns blaze.elm.compiler.macros (:require - [blaze.elm.compiler.core :as core])) + [blaze.elm.compiler.core :as core] + [blaze.elm.expression.cache :as-alias expr-cache])) + + +(set! *warn-on-reflection* true) (defn- compile-kw [name] (keyword "elm.compiler.type" (clojure.core/name name))) +(defn generate-binding-vector + "Creates a binding vector of at least `[operand-binding operand]` and + optionally `[operand-binding operand expr-binding expr-sym]` if `expr-binding` + is given." + [operand-binding operand expr-binding expr-sym] + (cond-> [operand-binding operand] expr-binding (conj expr-binding expr-sym))) + + +(defn generate-unop [name operand-sym operand-binding expr-binding expr-sym body] + (let [context-sym (gensym "context") + resource-sym (gensym "resource") + scope-sym (gensym "scope")] + `(reify core/Expression + (~'-static [~'_] + false) + (~'-eval [~'_ ~context-sym ~resource-sym ~scope-sym] + (let ~(generate-binding-vector + operand-binding `(core/-eval ~operand-sym ~context-sym ~resource-sym ~scope-sym) + expr-binding expr-sym) + ~@body)) + (~'-form [~'_] + (list (quote ~name) (core/-form ~operand-sym)))))) + + (defmacro defunop {:arglists '([name attr-map? bindings & body])} [name & more] (let [attr-map (when (map? (first more)) (first more)) more (if (map? (first more)) (next more) more) - [[operand-binding expr-binding] & body] more] - (if expr-binding - `(defmethod core/compile* ~(compile-kw name) - [context# expr#] - (let [operand# (core/compile* (merge context# ~attr-map) (:operand expr#))] - (if (core/static? operand#) - (let [~operand-binding operand# - ~expr-binding expr#] - ~@body) - (reify core/Expression - (~'-eval [~'_ context# resource# scope#] - (let [~operand-binding (core/-eval operand# context# resource# scope#) - ~expr-binding expr#] - ~@body)) - (~'-form [~'_] - (list (quote ~name) (core/-form operand#))))))) - `(defmethod core/compile* ~(compile-kw name) - [context# expr#] - (let [operand# (core/compile* (merge context# ~attr-map) (:operand expr#))] - (if (core/static? operand#) - (let [~operand-binding operand#] - ~@body) - (reify core/Expression - (~'-eval [~'_ context# resource# scope#] - (let [~operand-binding (core/-eval operand# context# resource# scope#)] - ~@body)) - (~'-form [~'_] - (list (quote ~name) (core/-form operand#)))))))))) + [[operand-binding expr-binding] & body] more + context-sym (gensym "context") + operand-sym (gensym "operand") + expr-sym (gensym "expr")] + `(defmethod core/compile* ~(compile-kw name) + [~context-sym ~expr-sym] + (let [~operand-sym (core/compile* (merge ~context-sym ~(dissoc attr-map :cache)) (:operand ~expr-sym))] + (if (core/static? ~operand-sym) + (let [~operand-binding ~operand-sym + ~(or expr-binding '_) ~expr-sym] + ~@body) + ~(generate-unop name operand-sym operand-binding expr-binding expr-sym body)))))) (defmacro defbinop @@ -58,6 +70,8 @@ ~op-2-binding operand-2#] ~@body) (reify core/Expression + (~'-static [~'_] + false) (~'-eval [~'_ context# resource# scope#] (let [~op-1-binding (core/-eval operand-1# context# resource# scope#) ~op-2-binding (core/-eval operand-2# context# resource# scope#)] @@ -75,11 +89,16 @@ operand-2# (core/compile* context# operand-2#) operand-3# (core/compile* context# operand-3#)] (reify core/Expression + (~'-static [~'_] + false) (~'-eval [~'_ context# resource# scope#] (let [~op-1-binding (core/-eval operand-1# context# resource# scope#) ~op-2-binding (core/-eval operand-2# context# resource# scope#) ~op-3-binding (core/-eval operand-3# context# resource# scope#)] - ~@body)))))) + ~@body)) + (~'-form [~'_] + (list (quote ~name) (core/-form operand-1#) (core/-form operand-2#) + (core/-form operand-3#))))))) (defmacro defnaryop @@ -89,6 +108,8 @@ [context# {operands# :operand}] (let [operands# (mapv #(core/compile* context# %) operands#)] (reify core/Expression + (~'-static [~'_] + false) (~'-eval [~'_ context# resource# scope#] (let [~operands-binding (mapv #(core/-eval % context# resource# scope#) operands#)] ~@body)) @@ -103,9 +124,13 @@ [context# {source# :source}] (let [source# (core/compile* context# source#)] (reify core/Expression + (~'-static [~'_] + false) (~'-eval [~'_ context# resource# scope#] (let [~source-binding (core/-eval source# context# resource# scope#)] - ~@body)))))) + ~@body)) + (~'-form [~'_] + (list (quote ~name) (core/-form source#))))))) (defmacro defunopp @@ -117,6 +142,8 @@ ~precision-binding (some-> precision# core/to-chrono-unit) ~(or expr-binding '_) expr#] (reify core/Expression + (~'-static [~'_] + false) (~'-eval [~'_ context# resource# scope#] (let [~operand-binding (core/-eval operand# context# resource# scope#)] ~@body)) @@ -142,6 +169,8 @@ ~precision-binding chrono-precision#] ~@body) (reify core/Expression + (~'-static [~'_] + false) (~'-eval [~'_ context# resource# scope#] (let [~op-1-binding (core/-eval operand-1# context# resource# scope#) ~op-2-binding (core/-eval operand-2# context# resource# scope#) diff --git a/modules/cql/src/blaze/elm/compiler/nullological_operators.clj b/modules/cql/src/blaze/elm/compiler/nullological_operators.clj index ed0bda1ee..522073948 100644 --- a/modules/cql/src/blaze/elm/compiler/nullological_operators.clj +++ b/modules/cql/src/blaze/elm/compiler/nullological_operators.clj @@ -28,6 +28,8 @@ (if (= "List" (:type operand)) (let [operand (core/compile* context operand)] (reify core/Expression + (-static [_] + false) (-eval [_ context resource scope] (reduce (fn [_ elem] @@ -38,10 +40,14 @@ (core/-eval operand context resource scope))))) (let [operand (core/compile* context operand)] (reify core/Expression + (-static [_] + false) (-eval [_ context resource scope] (core/-eval operand context resource scope)))))) (let [operands (mapv #(core/compile* context %) operands)] (reify core/Expression + (-static [_] + false) (-eval [_ context resource scope] (reduce (fn [_ operand] diff --git a/modules/cql/src/blaze/elm/compiler/parameters.clj b/modules/cql/src/blaze/elm/compiler/parameters.clj index 2789f37ce..a457bfb14 100644 --- a/modules/cql/src/blaze/elm/compiler/parameters.clj +++ b/modules/cql/src/blaze/elm/compiler/parameters.clj @@ -22,6 +22,8 @@ (defrecord ParameterRef [name] core/Expression + (-static [_] + false) (-eval [_ {:keys [parameters] :as context} _ _] (let [value (get parameters name ::not-found)] (if (identical? ::not-found value) diff --git a/modules/cql/src/blaze/elm/compiler/queries.clj b/modules/cql/src/blaze/elm/compiler/queries.clj index 7dd8203b6..b05f6a819 100644 --- a/modules/cql/src/blaze/elm/compiler/queries.clj +++ b/modules/cql/src/blaze/elm/compiler/queries.clj @@ -63,7 +63,7 @@ (-create [_ context resource scope] (filter #(core/-eval expr context resource (assoc scope alias %)))) (-form [_] - `(~'where ~(symbol alias) ~(core/-form expr)))) + `(~'where (~'fn [~(symbol alias)] ~(core/-form expr))))) (defn- where-xform-factory [alias expr] @@ -75,7 +75,7 @@ (-create [_ context resource scope] (map #(core/-eval expr context resource (assoc scope alias %)))) (-form [_] - `(~'return ~(symbol alias) ~(core/-form expr)))) + `(~'return (~'fn [~(symbol alias)] ~(core/-form expr))))) (defrecord DistinctXformFactory [] @@ -137,6 +137,8 @@ (defrecord EductionQueryExpression [xform-factory source] core/Expression + (-static [_] + false) (-eval [_ context resource scope] (coll/eduction (-create xform-factory context resource scope) @@ -151,6 +153,8 @@ (defrecord IntoVectorQueryExpression [xform-factory source] core/Expression + (-static [_] + false) (-eval [_ context resource scope] (into [] @@ -200,6 +204,8 @@ (defrecord SortQueryExpression [source sort-by-item] core/Expression + (-static [_] + false) (-eval [_ context resource scope] ;; TODO: build a comparator of all sort by items (->> (vec (core/-eval source context resource scope)) @@ -217,6 +223,8 @@ (defrecord XformSortQueryExpression [xform-factory source sort-by-item] core/Expression + (-static [_] + false) (-eval [_ context resource scope] ;; TODO: build a comparator of all sort by items (->> (into @@ -302,6 +310,8 @@ ;; 10.3. AliasRef (defrecord AliasRefExpression [key] core/Expression + (-static [_] + false) (-eval [_ _ _ scopes] (get scopes key)) (-form [_] diff --git a/modules/cql/src/blaze/elm/compiler/reusing_logic.clj b/modules/cql/src/blaze/elm/compiler/reusing_logic.clj index 8a4881096..0534253d6 100644 --- a/modules/cql/src/blaze/elm/compiler/reusing_logic.clj +++ b/modules/cql/src/blaze/elm/compiler/reusing_logic.clj @@ -31,6 +31,8 @@ (defrecord ExpressionRef [name] core/Expression + (-static [_] + false) (-eval [_ {:keys [expression-defs] :as context} resource _] (if-let [{:keys [expression]} (get expression-defs name)] (core/-eval expression context resource nil) @@ -70,6 +72,8 @@ ;; Unfiltered context. So we map the referenced expression over all ;; concrete resources. (reify core/Expression + (-static [_] + false) (-eval [_ {:keys [db expression-defs] :as context} _ _] (if-some [{:keys [expression]} (get expression-defs name)] (mapv @@ -104,6 +108,8 @@ (defrecord ToQuantityFunctionExpression [operand] core/Expression + (-static [_] + false) (-eval [_ context resource scope] (-to-quantity (core/-eval operand context resource scope))) (-form [_] @@ -112,13 +118,19 @@ (defrecord ToCodeFunctionExpression [operand] core/Expression + (-static [_] + false) (-eval [_ context resource scope] (let [{:keys [system version code]} (core/-eval operand context resource scope)] - (code/to-code (type/value system) (type/value version) (type/value code))))) + (code/to-code (type/value system) (type/value version) (type/value code)))) + (-form [_] + `(~'call "ToCode" ~(core/-form operand)))) (defrecord ToDateFunctionExpression [operand] core/Expression + (-static [_] + false) (-eval [_ context resource scope] (type/value (core/-eval operand context resource scope))) (-form [_] @@ -127,6 +139,8 @@ (defrecord ToDateTimeFunctionExpression [operand] core/Expression + (-static [_] + false) (-eval [_ {:keys [now] :as context} resource scope] (p/to-date-time (type/value (core/-eval operand context resource scope)) now)) (-form [_] @@ -135,6 +149,8 @@ (defrecord ToStringFunctionExpression [operand] core/Expression + (-static [_] + false) (-eval [_ context resource scope] (some-> (type/value (core/-eval operand context resource scope)) str)) (-form [_] @@ -158,6 +174,8 @@ (defrecord ToIntervalFunctionExpression [operand] core/Expression + (-static [_] + false) (-eval [_ context resource scope] (-to-interval (core/-eval operand context resource scope) context)) (-form [_] @@ -210,6 +228,8 @@ (defmethod core/compile* :elm.compiler.type/operand-ref [_ {:keys [name]}] (reify core/Expression + (-static [_] + false) (-eval [_ _ _ scope] (scope name)) (-form [_] diff --git a/modules/cql/src/blaze/elm/compiler/string_operators.clj b/modules/cql/src/blaze/elm/compiler/string_operators.clj index 7e479d36b..7ee4c1d17 100644 --- a/modules/cql/src/blaze/elm/compiler/string_operators.clj +++ b/modules/cql/src/blaze/elm/compiler/string_operators.clj @@ -21,14 +21,22 @@ separator (some->> separator (core/compile* context))] (if separator (reify core/Expression + (-static [_] + false) (-eval [_ context resource scope] (when-let [source (core/-eval source context resource scope)] (string/combine (core/-eval separator context resource scope) - source)))) + source))) + (-form [_] + (list 'combine (core/-form source) (core/-form separator)))) (reify core/Expression + (-static [_] + false) (-eval [_ context resource scope] (when-let [source (core/-eval source context resource scope)] - (string/combine source))))))) + (string/combine source))) + (-form [_] + (list 'combine (core/-form source))))))) ;; 17.2. Concatenate @@ -53,10 +61,14 @@ (let [pattern (core/compile* context pattern) string (core/compile* context string)] (reify core/Expression + (-static [_] + false) (-eval [_ context resource scope] (when-let [^String pattern (core/-eval pattern context resource scope)] (when-let [^String string (core/-eval string context resource scope)] - (.lastIndexOf string pattern))))))) + (.lastIndexOf string pattern)))) + (-form [_] + (list 'last-position-of (core/-form pattern) (core/-form string)))))) ;; 17.8. Length @@ -81,10 +93,14 @@ (let [pattern (core/compile* context pattern) string (core/compile* context string)] (reify core/Expression + (-static [_] + false) (-eval [_ context resource scope] (when-let [^String pattern (core/-eval pattern context resource scope)] (when-let [^String string (core/-eval string context resource scope)] - (.indexOf string pattern))))))) + (.indexOf string pattern)))) + (-form [_] + (list 'position-of (core/-form pattern) (core/-form string)))))) ;; 17.13. ReplaceMatches @@ -100,6 +116,8 @@ separator (some->> separator (core/compile* context))] (if separator (reify core/Expression + (-static [_] + false) (-eval [_ context resource scope] (when-let [string (core/-eval string context resource scope)] (if (= "" string) @@ -121,11 +139,17 @@ (conj result (str (.append acc char)))))) ;; TODO: implement split with more than one char. (throw (Exception. "TODO: implement split with separators longer than one char."))) - [string]))))) + [string])))) + (-form [_] + (list 'split (core/-form string) (core/-form separator)))) (reify core/Expression + (-static [_] + false) (-eval [_ context resource scope] (when-let [string (core/-eval string context resource scope)] - [string])))))) + [string])) + (-form [_] + (list 'split (core/-form string))))))) ;; 17.16. StartsWith @@ -142,18 +166,27 @@ length (some->> length (core/compile* context))] (if length (reify core/Expression + (-static [_] + false) (-eval [_ context resource scope] (when-let [^String string (core/-eval string context resource scope)] (when-let [start-index (core/-eval start-index context resource scope)] (when (and (<= 0 start-index) (< start-index (count string))) (subs string start-index (min (+ start-index length) - (count string)))))))) + (count string))))))) + (-form [_] + (list 'substring (core/-form string) (core/-form start-index) + (core/-form length)))) (reify core/Expression + (-static [_] + false) (-eval [_ context resource scope] (when-let [^String string (core/-eval string context resource scope)] (when-let [start-index (core/-eval start-index context resource scope)] (when (and (<= 0 start-index) (< start-index (count string))) - (subs string start-index))))))))) + (subs string start-index))))) + (-form [_] + (list 'substring (core/-form string) (core/-form start-index))))))) ;; 17.18. Upper diff --git a/modules/cql/src/blaze/elm/compiler/structured_values.clj b/modules/cql/src/blaze/elm/compiler/structured_values.clj index b5a343035..0b649a208 100644 --- a/modules/cql/src/blaze/elm/compiler/structured_values.clj +++ b/modules/cql/src/blaze/elm/compiler/structured_values.clj @@ -6,11 +6,9 @@ (:require [blaze.anomaly :as ba :refer [throw-anom]] [blaze.coll.core :as coll] - [blaze.db.api :as d] [blaze.elm.code :as code] [blaze.elm.compiler.core :as core] [blaze.elm.protocols :as p] - [blaze.fhir.spec :as fhir-spec] [blaze.fhir.spec.type :as type] [clojure.string :as str]) (:import @@ -21,16 +19,6 @@ ;; 2.1. Tuple -(defrecord TupleExpression [elements] - core/Expression - (-eval [_ context resource scope] - (reduce-kv - (fn [r key value] - (assoc r key (core/-eval value context resource scope))) - {} - elements))) - - (defn- invalid-structured-type-access-msg [key] (format "Invalid structured type access with key `%s` on a collection." key)) @@ -41,6 +29,7 @@ :key key :first-elem (coll/first coll))) + (extend-protocol p/StructuredType IReduceInit (get [coll key] @@ -63,7 +52,21 @@ (let [elements (compile-elements context elements)] (if (every? core/static? (vals elements)) elements - (->TupleExpression elements)))) + (reify core/Expression + (-static [_] + false) + (-eval [_ context resource scope] + (reduce-kv + (fn [r key value] + (assoc r key (core/-eval value context resource scope))) + {} + elements)) + (-form [_] + (reduce-kv + (fn [r key value] + (assoc r key (core/-form value))) + {} + elements)))))) ;; 2.2. Instance @@ -78,54 +81,52 @@ ;; 2.3. Property -(defn- pull [db x] - (if (d/resource-handle? x) - @(d/pull-content db x) - x)) - - -(defn- get-property [db key x] - (if (fhir-spec/fhir-type x) - (get (pull db x) key) - (p/get x key))) - - (defrecord SourcePropertyExpression [source key] core/Expression - (-eval [_ {:keys [db] :as context} resource scope] - (get-property db key (core/-eval source context resource scope))) + (-static [_] + false) + (-eval [_ context resource scope] + (p/get (core/-eval source context resource scope) key)) (-form [_] `(~key ~(core/-form source)))) (defrecord SourcePropertyValueExpression [source key] core/Expression - (-eval [_ {:keys [db] :as context} resource scope] - (type/value (get-property db key (core/-eval source context resource scope)))) + (-static [_] + false) + (-eval [_ context resource scope] + (type/value (p/get (core/-eval source context resource scope) key))) (-form [_] `(:value (~key ~(core/-form source))))) (defrecord SingleScopePropertyExpression [key] core/Expression - (-eval [_ {:keys [db]} _ value] - (get-property db key value)) + (-static [_] + false) + (-eval [_ _ _ value] + (p/get value key)) (-form [_] `(~key ~'default))) (defrecord ScopePropertyExpression [scope-key key] core/Expression - (-eval [_ {:keys [db]} _ scope] - (get-property db key (get scope scope-key))) + (-static [_] + false) + (-eval [_ _ _ scope] + (p/get (get scope scope-key) key)) (-form [_] `(~key ~(symbol (name scope-key))))) (defrecord ScopePropertyValueExpression [scope-key key] core/Expression - (-eval [_ {:keys [db]} _ scope] - (type/value (get-property db key (get scope scope-key)))) + (-static [_] + false) + (-eval [_ _ _ scope] + (type/value (p/get (get scope scope-key) key))) (-form [_] `(:value (~key ~(symbol (name scope-key)))))) diff --git a/modules/cql/src/blaze/elm/compiler/type_operators.clj b/modules/cql/src/blaze/elm/compiler/type_operators.clj index d89f98f25..2ddbae60c 100644 --- a/modules/cql/src/blaze/elm/compiler/type_operators.clj +++ b/modules/cql/src/blaze/elm/compiler/type_operators.clj @@ -19,16 +19,6 @@ ;; 22.1. As -(defrecord AsExpression [operand type pred] - core/Expression - (-eval [_ context resource scope] - (let [value (core/-eval operand context resource scope)] - (when (pred value) - value))) - (-form [_] - `(~'as ~type ~(core/-form operand)))) - - (defn- matches-elm-named-type-fn [type-name] (case type-name "Boolean" ['elm/boolean boolean?] @@ -92,7 +82,15 @@ [context {:keys [operand] :as expression}] (when-some [operand (core/compile* context operand)] (let [[type pred] (matches-type-fn expression)] - (->AsExpression operand type pred)))) + (reify core/Expression + (-static [_] + false) + (-eval [_ context resource scope] + (let [value (core/-eval operand context resource scope)] + (when (pred value) + value))) + (-form [_] + `(~'as ~type ~(core/-form operand))))))) ;; TODO 22.2. CanConvert @@ -104,16 +102,16 @@ ;; 22.4. Children -(defrecord ChildrenOperatorExpression [source] - core/Expression - (-eval [_ context resource scope] - (p/children (core/-eval source context resource scope)))) - - (defmethod core/compile* :elm.compiler.type/children [context {:keys [source]}] (when-let [source (core/compile* context source)] - (->ChildrenOperatorExpression source))) + (reify core/Expression + (-static [_] + false) + (-eval [_ context resource scope] + (p/children (core/-eval source context resource scope))) + (-form [_] + (list 'children (core/-form source)))))) ;; TODO 22.5. Convert @@ -131,39 +129,35 @@ ;; 22.8. ConvertsToDate -(defrecord ConvertsToDateOperatorExpression [operand] - core/Expression - (-eval [_ {:keys [now] :as context} resource scope] - (when-let [operand (core/-eval operand context resource scope)] - (when (some? operand) - (some? (p/to-date operand now))))) - (-form [_] - (list 'converts-to-date (core/-form operand)))) - - (defmethod core/compile* :elm.compiler.type/converts-to-date [context {:keys [operand]}] (when-let [operand (core/compile* context operand)] - (->ConvertsToDateOperatorExpression operand))) + (reify core/Expression + (-static [_] + false) + (-eval [_ {:keys [now] :as context} resource scope] + (when-let [operand (core/-eval operand context resource scope)] + (when (some? operand) + (some? (p/to-date operand now))))) + (-form [_] + (list 'converts-to-date (core/-form operand)))))) ;; 22.9. ConvertsToDateTime -(defrecord ConvertsToDateTimeOperatorExpression [operand] - core/Expression - (-eval [_ {:keys [now] :as context} resource scope] - (when-let [operand (core/-eval operand context resource scope)] - (when (some? operand) - (some? (p/to-date-time operand now))))) - (-form [_] - (list 'converts-to-date-time (core/-form operand)))) - - (defmethod core/compile* :elm.compiler.type/converts-to-date-time [context {:keys [operand]}] (when-let [operand (core/compile* context operand)] (if (system/date? operand) (some? (p/to-date-time operand nil)) - (->ConvertsToDateTimeOperatorExpression operand)))) + (reify core/Expression + (-static [_] + false) + (-eval [_ {:keys [now] :as context} resource scope] + (when-let [operand (core/-eval operand context resource scope)] + (when (some? operand) + (some? (p/to-date-time operand now))))) + (-form [_] + (list 'converts-to-date-time (core/-form operand))))))) ;; 22.10. ConvertsToDecimal @@ -203,44 +197,33 @@ ;; 22.16. ConvertsToTime -(defrecord ConvertsToTimeOperatorExpression [operand] - core/Expression - (-eval [_ {:keys [now] :as context} resource scope] - (when-let [operand (core/-eval operand context resource scope)] - (when (some? operand) - (some? (p/to-time operand now))))) - (-form [_] - (list 'converts-to-time (core/-form operand)))) - - (defmethod core/compile* :elm.compiler.type/converts-to-time [context {:keys [operand]}] (when-let [operand (core/compile* context operand)] - (->ConvertsToTimeOperatorExpression operand))) + (reify core/Expression + (-static [_] + false) + (-eval [_ {:keys [now] :as context} resource scope] + (when-some [operand (core/-eval operand context resource scope)] + (some? (p/to-time operand now)))) + (-form [_] + (list 'converts-to-time (core/-form operand)))))) ;; 22.17. Descendents -(defrecord DescendentsOperatorExpression [source] - core/Expression - (-eval [_ context resource scope] - (p/descendents (core/-eval source context resource scope)))) - - (defmethod core/compile* :elm.compiler.type/descendents [context {:keys [source]}] (when-let [source (core/compile* context source)] - (->DescendentsOperatorExpression source))) + (reify core/Expression + (-static [_] + false) + (-eval [_ context resource scope] + (p/descendents (core/-eval source context resource scope))) + (-form [_] + (list 'descendents (core/-form source)))))) ;; 22.18. Is -(defrecord IsExpression [operand type pred] - core/Expression - (-eval [_ context resource scope] - (pred (core/-eval operand context resource scope))) - (-form [_] - `(~'is ~type ~(core/-form operand)))) - - (defn- matches-elm-named-type-is [type-name] (case type-name "Boolean" ['elm/boolean boolean?] @@ -288,8 +271,15 @@ (defmethod core/compile* :elm.compiler.type/is [context {:keys [operand] :as expression}] - (let [[type pred] (matches-type-is expression)] - (->IsExpression (core/compile* context operand) type pred))) + (let [[type pred] (matches-type-is expression) + operand (core/compile* context operand)] + (reify core/Expression + (-static [_] + false) + (-eval [_ context resource scope] + (pred (core/-eval operand context resource scope))) + (-form [_] + `(~'is ~type ~(core/-form operand)))))) ;; 22.19. ToBoolean @@ -309,33 +299,33 @@ ;; 22.22. ToDate -(defrecord ToDateOperatorExpression [operand] - core/Expression - (-eval [_ {:keys [now] :as context} resource scope] - (p/to-date (core/-eval operand context resource scope) now))) - - (defmethod core/compile* :elm.compiler.type/to-date [context {:keys [operand]}] (when-let [operand (core/compile* context operand)] - (->ToDateOperatorExpression operand))) + (if (system/date? operand) + (p/to-date operand nil) + (reify core/Expression + (-static [_] + false) + (-eval [_ {:keys [now] :as context} resource scope] + (p/to-date (core/-eval operand context resource scope) now)) + (-form [_] + (list 'to-date (core/-form operand))))))) ;; 22.23. ToDateTime -(defrecord ToDateTimeOperatorExpression [operand] - core/Expression - (-eval [_ {:keys [now] :as context} resource scope] - (p/to-date-time (core/-eval operand context resource scope) now)) - (-form [_] - (list 'to-date-time (core/-form operand)))) - - (defmethod core/compile* :elm.compiler.type/to-date-time [context {:keys [operand]}] (when-let [operand (core/compile* context operand)] (if (system/date? operand) (p/to-date-time operand nil) - (->ToDateTimeOperatorExpression operand)))) + (reify core/Expression + (-static [_] + false) + (-eval [_ {:keys [now] :as context} resource scope] + (p/to-date-time (core/-eval operand context resource scope) now)) + (-form [_] + (list 'to-date-time (core/-form operand))))))) ;; 22.24. ToDecimal @@ -374,13 +364,13 @@ ;; 22.31. ToTime -(defrecord ToTimeOperatorExpression [operand] - core/Expression - (-eval [_ {:keys [now] :as context} resource scope] - (p/to-time (core/-eval operand context resource scope) now))) - - (defmethod core/compile* :elm.compiler.type/to-time [context {:keys [operand]}] (when-let [operand (core/compile* context operand)] - (->ToTimeOperatorExpression operand))) + (reify core/Expression + (-static [_] + false) + (-eval [_ {:keys [now] :as context} resource scope] + (p/to-time (core/-eval operand context resource scope) now)) + (-form [_] + (list 'to-time (core/-form operand)))))) diff --git a/modules/cql/src/blaze/elm/compiler_spec.clj b/modules/cql/src/blaze/elm/compiler_spec.clj index 4baded507..fe1ce022d 100644 --- a/modules/cql/src/blaze/elm/compiler_spec.clj +++ b/modules/cql/src/blaze/elm/compiler_spec.clj @@ -1,6 +1,6 @@ (ns blaze.elm.compiler-spec (:require - [blaze.elm.compiler :as compiler] + [blaze.elm.compiler :as c] [blaze.elm.compiler.core :as core] [blaze.elm.compiler.spec] [blaze.elm.spec] @@ -8,6 +8,6 @@ [clojure.spec.alpha :as s])) -(s/fdef compiler/compile +(s/fdef c/compile :args (s/cat :context :elm/compile-context :expression :elm/expression) :ret core/expr?) diff --git a/modules/cql/src/blaze/elm/expression/spec.clj b/modules/cql/src/blaze/elm/expression/spec.clj new file mode 100644 index 000000000..0683e3afc --- /dev/null +++ b/modules/cql/src/blaze/elm/expression/spec.clj @@ -0,0 +1,21 @@ +(ns blaze.elm.expression.spec + (:require + [blaze.db.api-spec] + [blaze.elm.compiler :as-alias c] + [blaze.elm.expression :as-alias expr] + [blaze.elm.spec] + [clojure.spec.alpha :as s] + [java-time.api :as time])) + + +(s/def ::now + time/offset-date-time?) + + +(s/def ::parameters + (s/map-of :elm/name ::c/expression)) + + +(s/def ::expr/context + (s/keys :req-un [:blaze.db/db ::now] + :opt-un [::c/expression-defs ::parameters])) diff --git a/modules/cql/src/blaze/elm/expression_spec.clj b/modules/cql/src/blaze/elm/expression_spec.clj index 6097d5eaf..307666857 100644 --- a/modules/cql/src/blaze/elm/expression_spec.clj +++ b/modules/cql/src/blaze/elm/expression_spec.clj @@ -1,30 +1,17 @@ (ns blaze.elm.expression-spec (:require [blaze.db.api-spec] - [blaze.elm.compiler :as-alias compiler] + [blaze.elm.compiler :as-alias c] + [blaze.elm.compiler.external-data :as ed] [blaze.elm.compiler.library-spec] [blaze.elm.compiler.spec] [blaze.elm.expression :as expr] + [blaze.elm.expression.spec] [blaze.fhir.spec] - [clojure.spec.alpha :as s] - [java-time.api :as time])) - - -(s/def ::now - time/offset-date-time?) - - -(s/def ::parameters - (s/map-of :elm/name ::compiler/expression)) - - -(s/def :blaze.elm.expression/context - (s/keys :req-un [:blaze.db/db ::now] - :opt-un [::compiler/expression-defs ::parameters])) + [clojure.spec.alpha :as s])) (s/fdef expr/eval - :args (s/cat :context :blaze.elm.expression/context - :expression :blaze.elm.compiler/expression - :resource (s/nilable (s/or :resource :blaze/resource - :resource-handle :blaze.db/resource-handle)))) + :args (s/cat :context ::expr/context + :expression ::c/expression + :resource (s/nilable ed/resource?))) diff --git a/modules/cql/src/blaze/elm/quantity.clj b/modules/cql/src/blaze/elm/quantity.clj index 25b925ab4..a13adecef 100644 --- a/modules/cql/src/blaze/elm/quantity.clj +++ b/modules/cql/src/blaze/elm/quantity.clj @@ -5,6 +5,7 @@ https://cql.hl7.org/04-logicalspecification.html." (:require [blaze.anomaly :as ba :refer [throw-anom]] + [blaze.elm.compiler.core :as core] [blaze.elm.protocols :as p] [cuerdas.core :as c-str]) (:import @@ -73,6 +74,16 @@ (Quantities/getQuantity ^Number value ^Unit (parse-unit unit))) +(extend-protocol core/Expression + Quantity + (-static [_] + true) + (-eval [quantity _ _ _] + quantity) + (-form [quantity] + `(~'quantity ~(.getValue quantity) ~(format-unit (.getUnit quantity))))) + + (defprotocol QuantityDivide (quantity-divide [divisor quantity])) diff --git a/modules/cql/test/blaze/cql_translator_test.clj b/modules/cql/test/blaze/cql_translator_test.clj index 596178f1d..6a49a275d 100644 --- a/modules/cql/test/blaze/cql_translator_test.clj +++ b/modules/cql/test/blaze/cql_translator_test.clj @@ -24,15 +24,18 @@ (testing "Simple Retrieve" (given-translation "library Test - using FHIR version '3.0.0' + using FHIR version '4.0.0' define Patients: [Patient]" [0 :expression :type] := "Retrieve" - [0 :expression :dataType] := "{http://hl7.org/fhir}Patient")) + [0 :expression :dataType] := "{http://hl7.org/fhir}Patient" + [0 :expression :resultTypeSpecifier :type] := "ListTypeSpecifier" + [0 :expression :resultTypeSpecifier :elementType :type] := "NamedTypeSpecifier" + [0 :expression :resultTypeSpecifier :elementType :name] := "{http://hl7.org/fhir}Patient")) - (testing "Retrieve with Code" + (testing "Retrieve with code" (given-translation "library Test - using FHIR version '3.0.0' + using FHIR version '4.0.0' codesystem test: 'test' code T0: '0' from test define Observations: [Observation: T0]" @@ -40,7 +43,29 @@ [0 :expression :dataType] := "{http://hl7.org/fhir}Observation" [0 :expression :codes :type] := "ToList" [0 :expression :codes :operand :type] := "CodeRef" - [0 :expression :codes :operand :name] := "T0")) + [0 :expression :codes :operand :name] := "T0" + [0 :expression :resultTypeSpecifier :type] := "ListTypeSpecifier" + [0 :expression :resultTypeSpecifier :elementType :type] := "NamedTypeSpecifier" + [0 :expression :resultTypeSpecifier :elementType :name] := "{http://hl7.org/fhir}Observation")) + + (testing "Query" + (given-translation + "library Test + using FHIR version '4.0.0' + include FHIRHelpers version '4.0.0' + define Observations: [Observation] O where O.status = 'final'" + [0 :expression :type] := "Query" + [0 :expression :source 0 :alias] := "O" + [0 :expression :source 0 :expression :type] := "Retrieve" + [0 :expression :source 0 :expression :dataType] := "{http://hl7.org/fhir}Observation" + [0 :expression :source 0 :expression :resultTypeSpecifier :type] := "ListTypeSpecifier" + [0 :expression :source 0 :expression :resultTypeSpecifier :elementType :type] := "NamedTypeSpecifier" + [0 :expression :source 0 :expression :resultTypeSpecifier :elementType :name] := "{http://hl7.org/fhir}Observation" + [0 :expression :where :type] := "Equal" + [0 :expression :where :resultTypeName] := "{urn:hl7-org:elm-types:r1}Boolean" + [0 :expression :where :operand 0 :type] := "FunctionRef" + [0 :expression :where :operand 0 :operand 0 :type] := "Property" + [0 :expression :where :operand 0 :operand 0 :scope] := "O")) (testing "Returns a valid :elm/library" (are [cql] (s/valid? :elm/library (translate cql)) @@ -68,8 +93,3 @@ define Error: (") ::anom/category := ::anom/incorrect ::anom/message := "Syntax error at "))) - - -(comment - (translate "library \"schaedeldachfraktur\"\nusing FHIR version '4.0.0'\ninclude FHIRHelpers version '4.0.0'\n\ncodesystem icd10: 'http://fhir.de/CodeSystem/bfarm/icd-10-gm'\ncode \"Schรคdeldachfraktur\": 'S02.0' from icd10\n\ncontext Patient\n\ndefine InInitialPopulation:\n Length([Condition: \"Schรคdeldachfraktur\"]) >= 2\n") - ) diff --git a/modules/cql/test/blaze/elm/compiler/aggregate_operators_test.clj b/modules/cql/test/blaze/elm/compiler/aggregate_operators_test.clj index f57e65ef1..278d49ddb 100644 --- a/modules/cql/test/blaze/elm/compiler/aggregate_operators_test.clj +++ b/modules/cql/test/blaze/elm/compiler/aggregate_operators_test.clj @@ -7,6 +7,7 @@ [blaze.elm.compiler :as c] [blaze.elm.compiler.aggregate-operators] [blaze.elm.compiler.core :as core] + [blaze.elm.compiler.core-spec] [blaze.elm.compiler.test-util :as tu] [blaze.elm.literal :as elm] [blaze.elm.literal-spec] @@ -48,7 +49,11 @@ #elm/list [{:type "Null"}] true #elm/list [] true - {:type "Null"} true))) + {:type "Null"} true)) + + (tu/testing-unary-dynamic elm/all-true) + + (tu/testing-unary-form elm/all-true)) ;; 21.2. AnyTrue @@ -70,7 +75,11 @@ #elm/list [{:type "Null"}] false #elm/list [] false - {:type "Null"} false))) + {:type "Null"} false)) + + (tu/testing-unary-dynamic elm/any-true) + + (tu/testing-unary-form elm/any-true)) ;; 21.3. Avg @@ -92,7 +101,11 @@ #elm/list [{:type "Null"}] nil #elm/list [] nil - {:type "Null"} nil))) + {:type "Null"} nil)) + + (tu/testing-unary-dynamic elm/avg) + + (tu/testing-unary-form elm/avg)) ;; 21.4. Count @@ -116,7 +129,11 @@ #elm/list [{:type "Null"}] 0 #elm/list [] 0 - {:type "Null"} 0))) + {:type "Null"} 0)) + + (tu/testing-unary-dynamic elm/count) + + (tu/testing-unary-form elm/count)) ;; 21.5. GeometricMean @@ -139,7 +156,11 @@ #elm/list [{:type "Null"}] nil #elm/list [] nil - {:type "Null"} nil))) + {:type "Null"} nil)) + + (tu/testing-unary-dynamic elm/geometric-mean) + + (tu/testing-unary-form elm/geometric-mean)) ;; 21.6. Product @@ -162,7 +183,11 @@ #elm/list [{:type "Null"}] nil #elm/list [] nil - {:type "Null"} nil))) + {:type "Null"} nil)) + + (tu/testing-unary-dynamic elm/product) + + (tu/testing-unary-form elm/product)) ;; 21.7. Max @@ -186,7 +211,11 @@ #elm/list [{:type "Null"}] nil #elm/list [] nil - {:type "Null"} nil))) + {:type "Null"} nil)) + + (tu/testing-unary-dynamic elm/max) + + (tu/testing-unary-form elm/max)) ;; 21.8. Median @@ -209,7 +238,11 @@ #elm/list [{:type "Null"}] nil #elm/list [] nil - {:type "Null"} nil))) + {:type "Null"} nil)) + + (tu/testing-unary-dynamic elm/median) + + (tu/testing-unary-form elm/median)) ;; 21.9. Min @@ -233,7 +266,11 @@ #elm/list [{:type "Null"}] nil #elm/list [] nil - {:type "Null"} nil))) + {:type "Null"} nil)) + + (tu/testing-unary-dynamic elm/min) + + (tu/testing-unary-form elm/min)) ;; 21.10. Mode @@ -256,7 +293,11 @@ #elm/list [{:type "Null"}] nil #elm/list [] nil - {:type "Null"} nil))) + {:type "Null"} nil)) + + (tu/testing-unary-dynamic elm/mode) + + (tu/testing-unary-form elm/mode)) ;; 21.11. PopulationVariance @@ -277,7 +318,11 @@ #elm/list [{:type "Null"}] nil #elm/list [] nil - {:type "Null"} nil))) + {:type "Null"} nil)) + + (tu/testing-unary-dynamic elm/population-variance) + + (tu/testing-unary-form elm/population-variance)) ;; 21.12. PopulationStdDev @@ -298,7 +343,11 @@ #elm/list [{:type "Null"}] nil #elm/list [] nil - {:type "Null"} nil))) + {:type "Null"} nil)) + + (tu/testing-unary-dynamic elm/population-std-dev) + + (tu/testing-unary-form elm/population-std-dev)) ;; 21.13. Sum @@ -320,7 +369,11 @@ #elm/list [{:type "Null"}] nil #elm/list [] nil - {:type "Null"} nil))) + {:type "Null"} nil)) + + (tu/testing-unary-dynamic elm/sum) + + (tu/testing-unary-form elm/sum)) ;; 21.14. StdDev @@ -341,7 +394,11 @@ #elm/list [{:type "Null"}] nil #elm/list [] nil - {:type "Null"} nil))) + {:type "Null"} nil)) + + (tu/testing-unary-dynamic elm/std-dev) + + (tu/testing-unary-form elm/std-dev)) ;; 21.15. Variance @@ -362,4 +419,8 @@ #elm/list [{:type "Null"}] nil #elm/list [] nil - {:type "Null"} nil))) + {:type "Null"} nil)) + + (tu/testing-unary-dynamic elm/variance) + + (tu/testing-unary-form elm/variance)) diff --git a/modules/cql/test/blaze/elm/compiler/arithmetic_operators_test.clj b/modules/cql/test/blaze/elm/compiler/arithmetic_operators_test.clj index 3b8148ac4..870c110ec 100644 --- a/modules/cql/test/blaze/elm/compiler/arithmetic_operators_test.clj +++ b/modules/cql/test/blaze/elm/compiler/arithmetic_operators_test.clj @@ -8,6 +8,7 @@ [blaze.elm.compiler :as c] [blaze.elm.compiler.arithmetic-operators-spec] [blaze.elm.compiler.core :as core] + [blaze.elm.compiler.core-spec] [blaze.elm.compiler.test-util :as tu] [blaze.elm.date-time :as date-time] [blaze.elm.date-time-spec] @@ -86,8 +87,15 @@ [0M "m"] (quantity/quantity 0M "m") [1M "m"] (quantity/quantity 1M "m")))) + (testing "Dynamic" + (are [elm res] (= res (tu/dynamic-compile-eval (elm/abs elm))) + #elm/parameter-ref "1" 1 + #elm/parameter-ref "-1" 1)) + (tu/testing-unary-null elm/abs) + (tu/testing-unary-dynamic elm/abs) + (tu/testing-unary-form elm/abs)) @@ -362,6 +370,8 @@ #elm/time "00:00:00" #elm/quantity [1 "minute"] (date-time/local-time 0 1 0) #elm/time "00:00:00" #elm/quantity [1 "second"] (date-time/local-time 0 0 1))) + (tu/testing-binary-dynamic elm/add) + (tu/testing-binary-form elm/add)) @@ -378,6 +388,8 @@ (tu/testing-unary-null elm/ceiling) + (tu/testing-unary-dynamic elm/ceiling) + (tu/testing-unary-form elm/ceiling)) @@ -468,6 +480,8 @@ (let [elm (elm/equal [(elm/multiply [(elm/divide [decimal decimal]) decimal]) decimal])] (true? (core/-eval (c/compile {} elm) {} nil nil)))))) + (tu/testing-binary-dynamic elm/divide) + (tu/testing-binary-form elm/divide)) @@ -483,6 +497,8 @@ (tu/testing-unary-null elm/exp) + (tu/testing-unary-dynamic elm/exp) + (tu/testing-unary-form elm/exp)) @@ -499,6 +515,8 @@ (tu/testing-unary-null elm/floor) + (tu/testing-unary-dynamic elm/floor) + (tu/testing-unary-form elm/floor)) @@ -543,6 +561,8 @@ (tu/testing-binary-null elm/log #elm/decimal "1.1")) + (tu/testing-binary-dynamic elm/log) + (tu/testing-binary-form elm/log)) @@ -587,6 +607,8 @@ (tu/testing-unary-null elm/ln) + (tu/testing-unary-dynamic elm/ln) + (tu/testing-unary-form elm/ln)) @@ -714,6 +736,8 @@ #elm/integer "1" #elm/integer "0" nil #elm/decimal "1" #elm/decimal "0" nil)) + (tu/testing-binary-dynamic elm/modulo) + (tu/testing-binary-form elm/modulo)) @@ -757,6 +781,8 @@ (tu/testing-binary-null elm/multiply #elm/quantity [1])) + (tu/testing-binary-dynamic elm/multiply) + (tu/testing-binary-form elm/multiply)) @@ -787,6 +813,8 @@ (tu/testing-unary-null elm/negate) + (tu/testing-unary-dynamic elm/negate) + (tu/testing-unary-form elm/negate)) @@ -821,6 +849,8 @@ #elm/decimal "10" #elm/integer "2" 100M #elm/decimal "10" #elm/integer "2" 100M)) + (tu/testing-binary-dynamic elm/power) + (tu/testing-binary-form elm/power)) @@ -905,6 +935,8 @@ (tu/testing-unary-null elm/predecessor) + (tu/testing-unary-dynamic elm/predecessor) + (tu/testing-unary-form elm/predecessor)) @@ -954,14 +986,16 @@ eval-ctx {:parameters {"x" nil}}] (is (nil? (core/-eval expr eval-ctx nil nil)))))) - (testing "form" - (let [compile-ctx {:library {:parameters {:def [{:name "x"}]}}}] - (are [elm form] (= form (core/-form (c/compile compile-ctx elm))) - #elm/round [#elm/parameter-ref "x"] - '(round (param-ref "x")) - #elm/round [#elm/parameter-ref "x" #elm/integer "3"] - '(round (param-ref "x") 3))))) + (tu/testing-unary-null elm/round) + + (tu/testing-unary-dynamic elm/round) + + (tu/testing-unary-form elm/round) + + (tu/testing-binary-dynamic elm/round) + + (tu/testing-binary-form elm/round)) ;; 16.20. Subtract @@ -1181,6 +1215,8 @@ #elm/time "00:00:00" #elm/quantity [1 "minute"] (date-time/local-time 23 59 0) #elm/time "00:00:00" #elm/quantity [1 "second"] (date-time/local-time 23 59 59))) + (tu/testing-binary-dynamic elm/subtract) + (tu/testing-binary-form elm/subtract)) @@ -1252,6 +1288,8 @@ (tu/testing-unary-null elm/successor) + (tu/testing-unary-dynamic elm/successor) + (tu/testing-unary-form elm/successor)) @@ -1268,6 +1306,8 @@ (tu/testing-unary-null elm/truncate) + (tu/testing-unary-dynamic elm/truncate) + (tu/testing-unary-form elm/truncate)) @@ -1329,4 +1369,6 @@ (tu/testing-binary-null elm/truncated-divide #elm/integer "1" #elm/decimal "1.1")) + (tu/testing-binary-dynamic elm/truncated-divide) + (tu/testing-binary-form elm/truncated-divide)) diff --git a/modules/cql/test/blaze/elm/compiler/clinical_operators_test.clj b/modules/cql/test/blaze/elm/compiler/clinical_operators_test.clj index 8882f5555..ca1124371 100644 --- a/modules/cql/test/blaze/elm/compiler/clinical_operators_test.clj +++ b/modules/cql/test/blaze/elm/compiler/clinical_operators_test.clj @@ -7,6 +7,7 @@ [blaze.elm.compiler :as c] [blaze.elm.compiler.clinical-operators] [blaze.elm.compiler.core :as core] + [blaze.elm.compiler.core-spec] [blaze.elm.compiler.test-util :as tu] [blaze.elm.literal :as elm] [blaze.elm.literal-spec] @@ -77,6 +78,8 @@ (tu/testing-binary-null elm/calculate-age-at #elm/date"2018") (tu/testing-binary-null elm/calculate-age-at #elm/date-time"2018-01-01") + (tu/testing-binary-dynamic elm/calculate-age-at) + (tu/testing-binary-precision-form elm/calculate-age-at "year" "month" "day")) diff --git a/modules/cql/test/blaze/elm/compiler/clinical_values_test.clj b/modules/cql/test/blaze/elm/compiler/clinical_values_test.clj index c811064e9..1539ec8d8 100644 --- a/modules/cql/test/blaze/elm/compiler/clinical_values_test.clj +++ b/modules/cql/test/blaze/elm/compiler/clinical_values_test.clj @@ -9,7 +9,8 @@ [blaze.elm.compiler :as c] [blaze.elm.compiler.clinical-values] [blaze.elm.compiler.core :as core] - [blaze.elm.compiler.test-util :as tu] + [blaze.elm.compiler.core-spec] + [blaze.elm.compiler.test-util :as tu :refer [has-form]] [blaze.elm.concept-spec] [blaze.elm.date-time :as date-time] [blaze.elm.literal] @@ -51,11 +52,16 @@ (let [context {:library {:codeSystems - {:def [{:name "sys-def-115852" :id "system-115910"}]}}}] - (given (c/compile context #elm/code ["sys-def-115852" "code-115927"]) + {:def [{:name "sys-def-115852" :id "system-115910"}]}}} + expr (c/compile context #elm/code ["sys-def-115852" "code-115927"])] + + (given expr type := Code :system := "system-115910" - :code := "code-115927"))) + :code := "code-115927") + + (testing "form" + (has-form expr '(code "system-115910" nil "code-115927"))))) (testing "with version" (let [context @@ -64,12 +70,17 @@ {:def [{:name "sys-def-120434" :id "system-120411" - :version "version-120408"}]}}}] - (given (c/compile context #elm/code ["sys-def-120434" "code-120416"]) + :version "version-120408"}]}}} + expr (c/compile context #elm/code ["sys-def-120434" "code-120416"])] + + (given expr type := Code :system := "system-120411" :version := "version-120408" - :code := "code-120416"))) + :code := "code-120416") + + (testing "form" + (has-form expr '(code "system-120411" "version-120408" "code-120416"))))) (testing "missing code system" (let [context {:library {:codeSystems {:def []}}}] @@ -299,6 +310,12 @@ #elm/quantity [1 "s"] (quantity/quantity 1 "s") #elm/quantity [1 "cm2"] (quantity/quantity 1 "cm2"))) + (testing "form" + (are [elm res] (= res (c/form (c/compile {} elm))) + #elm/quantity [1] '(quantity 1 "1") + #elm/quantity [1 "s"] '(quantity 1 "s") + #elm/quantity [2 "cm2"] '(quantity 2 "cm2"))) + (testing "Periods" (satisfies-prop 100 (prop/for-all [period (s/gen :elm/period)] diff --git a/modules/cql/test/blaze/elm/compiler/comparison_operators_test.clj b/modules/cql/test/blaze/elm/compiler/comparison_operators_test.clj index 9282bdc50..8f334c693 100644 --- a/modules/cql/test/blaze/elm/compiler/comparison_operators_test.clj +++ b/modules/cql/test/blaze/elm/compiler/comparison_operators_test.clj @@ -7,6 +7,7 @@ [blaze.elm.compiler :as c] [blaze.elm.compiler.comparison-operators] [blaze.elm.compiler.core :as core] + [blaze.elm.compiler.core-spec] [blaze.elm.compiler.test-util :as tu] [blaze.elm.literal :as elm] [blaze.elm.literal-spec] @@ -260,6 +261,8 @@ (tu/testing-binary-null elm/equal (tu/code "a" "0"))) + (tu/testing-binary-dynamic elm/equal) + (tu/testing-binary-form elm/equal)) @@ -439,6 +442,8 @@ {:type "Null"} (tu/code "a" "0") false (tu/code "a" "0") {:type "Null"} false)) + (tu/testing-binary-dynamic elm/equivalent) + (tu/testing-binary-form elm/equivalent)) @@ -555,6 +560,8 @@ (tu/testing-binary-null elm/greater #elm/time "00:00:00")) + (tu/testing-binary-dynamic elm/greater) + (tu/testing-binary-form elm/greater)) @@ -683,6 +690,8 @@ (tu/testing-binary-null elm/greater-or-equal #elm/quantity [1])) + (tu/testing-binary-dynamic elm/greater-or-equal) + (tu/testing-binary-form elm/greater-or-equal)) @@ -815,6 +824,8 @@ (tu/testing-binary-null elm/less #elm/quantity [1])) + (tu/testing-binary-dynamic elm/less) + (tu/testing-binary-form elm/less)) @@ -936,6 +947,8 @@ (tu/testing-binary-null elm/less-or-equal #elm/quantity [1])) + (tu/testing-binary-dynamic elm/less-or-equal) + (tu/testing-binary-form elm/less-or-equal)) diff --git a/modules/cql/test/blaze/elm/compiler/conditional_operators_test.clj b/modules/cql/test/blaze/elm/compiler/conditional_operators_test.clj index ba936a8cb..f4ce27b4c 100644 --- a/modules/cql/test/blaze/elm/compiler/conditional_operators_test.clj +++ b/modules/cql/test/blaze/elm/compiler/conditional_operators_test.clj @@ -5,10 +5,11 @@ https://cql.hl7.org/04-logicalspecification.html." (:require [blaze.elm.compiler :as c] - [blaze.elm.compiler.test-util :as tu] + [blaze.elm.compiler.core :as core] + [blaze.elm.compiler.test-util :as tu :refer [has-form]] [blaze.elm.literal-spec] [clojure.spec.test.alpha :as st] - [clojure.test :as test :refer [are deftest testing]])) + [clojure.test :as test :refer [are deftest is testing]])) (st/instrument) @@ -25,6 +26,106 @@ (test/use-fixtures :each fixture) +;; 15.1. Case +;; +;; The Case operator allows for multiple conditional expressions to be chained +;; together in a single expression, rather than having to nest multiple If +;; operators. In addition, the comparand operand provides a variant on the case +;; that allows a single value to be compared in each conditional. +;; +;; If a comparand is not provided, the type of each when element of the +;; caseItems within the Case is expected to be boolean. If a comparand is +;; provided, the type of each when element of the caseItems within the Case is +;; expected to be of the same type as the comparand. An else element must always +;; be provided. +;; +;; The static type of the then argument within the first caseItem determines the +;; type of the result, and the then argument of each subsequent caseItem and the +;; else argument must be of that same type. +(deftest compile-case-test + ;; Case is only implemented dynamically + (testing "Dynamic" + (testing "multi-conditional" + (are [when res] (= res (tu/dynamic-compile-eval + {:type "Case" + :caseItem + [{:when when + :then #elm/integer "1"}] + :else #elm/integer "2"})) + + #elm/parameter-ref "true" 1 + #elm/parameter-ref "false" 2 + #elm/parameter-ref "nil" 2)) + + (testing "comparand-based" + (are [comparand res] (= res (tu/dynamic-compile-eval + {:type "Case" + :comparand comparand + :caseItem + [{:when #elm/string "a" + :then #elm/integer "1"}] + :else #elm/integer "2"})) + + #elm/parameter-ref "a" 1 + #elm/parameter-ref "b" 2 + #elm/parameter-ref "nil" 2))) + + (testing "form" + (testing "Static" + (testing "multi-conditional" + (let [expr (c/compile {} {:type "Case" + :caseItem + [{:when #elm/boolean "true" + :then #elm/integer "1"}] + :else #elm/integer "2"})] + (has-form expr '(case true 1 2)))) + + (testing "comparand-based" + (let [expr (c/compile {} {:type "Case" + :comparand #elm/string "a" + :caseItem + [{:when #elm/string "b" + :then #elm/integer "1"}] + :else #elm/integer "2"})] + (has-form expr '(case "a" "b" 1 2))))) + + (testing "Dynamic" + (testing "multi-conditional" + (let [expr (tu/dynamic-compile + {:type "Case" + :caseItem + [{:when #elm/parameter-ref "true" + :then #elm/integer "1"}] + :else #elm/integer "2"})] + (has-form expr '(case (param-ref "true") 1 2)))) + + (testing "comparand-based" + (let [expr (tu/dynamic-compile + {:type "Case" + :comparand #elm/parameter-ref "a" + :caseItem + [{:when #elm/parameter-ref "b" + :then #elm/integer "1"}] + :else #elm/integer "2"})] + (has-form expr '(case (param-ref "a") (param-ref "b") 1 2)))))) + + (testing "expression is dynamic" + (testing "multi-conditional" + (is (false? (core/-static (tu/dynamic-compile {:type "Case" + :caseItem + [{:when #elm/parameter-ref "true" + :then #elm/parameter-ref "1"}] + :else #elm/parameter-ref "2"}))))) + + (testing "comparand-based" + (is (false? (core/-static (tu/dynamic-compile {:type "Case" + :comparand #elm/parameter-ref "a" + :caseItem + [{:when #elm/parameter-ref "b" + :then #elm/parameter-ref "1"}] + :else #elm/parameter-ref "2"}))))))) + + ;; 15.2. If ;; ;; The If operator evaluates a condition, and returns the then argument if the @@ -43,4 +144,9 @@ (are [elm res] (= res (tu/dynamic-compile-eval elm)) #elm/if [#elm/parameter-ref "true" #elm/integer "1" #elm/integer "2"] 1 #elm/if [#elm/parameter-ref "false" #elm/integer "1" #elm/integer "2"] 2 - #elm/if [#elm/parameter-ref "nil" #elm/integer "1" #elm/integer "2"] 2))) + #elm/if [#elm/parameter-ref "nil" #elm/integer "1" #elm/integer "2"] 2)) + + (testing "expression is dynamic" + (is (false? (core/-static (tu/dynamic-compile #elm/if [#elm/parameter-ref "x" + #elm/parameter-ref "y" + #elm/parameter-ref "z"])))))) diff --git a/modules/cql/test/blaze/elm/compiler/core_spec.clj b/modules/cql/test/blaze/elm/compiler/core_spec.clj new file mode 100644 index 000000000..a05d179d7 --- /dev/null +++ b/modules/cql/test/blaze/elm/compiler/core_spec.clj @@ -0,0 +1,15 @@ +(ns blaze.elm.compiler.core-spec + (:require + [blaze.elm.compiler.core :as core] + [blaze.elm.compiler.core-spec] + [clojure.spec.alpha :as s])) + + +(s/fdef core/expr? + :args (s/cat :x any?) + :ret boolean?) + + +(s/fdef core/static? + :args (s/cat :x any?) + :ret boolean?) diff --git a/modules/cql/test/blaze/elm/compiler/date_time_operators_test.clj b/modules/cql/test/blaze/elm/compiler/date_time_operators_test.clj index c2c7585ad..10d819361 100644 --- a/modules/cql/test/blaze/elm/compiler/date_time_operators_test.clj +++ b/modules/cql/test/blaze/elm/compiler/date_time_operators_test.clj @@ -6,6 +6,7 @@ (:require [blaze.elm.compiler :as c] [blaze.elm.compiler.core :as core] + [blaze.elm.compiler.core-spec] [blaze.elm.compiler.test-util :as tu] [blaze.elm.date-time :as date-time] [blaze.elm.literal :as elm] @@ -18,7 +19,7 @@ [clojure.test.check.properties :as prop] [java-time.api :as time]) (:import - [blaze.fhir.spec.type.system DateDate DateYear DateYearMonth] + [blaze.fhir.spec.type.system DateDate] [java.time OffsetDateTime] [java.time.temporal Temporal])) @@ -164,20 +165,57 @@ eval-ctx {:parameters {"day" 23}}] (is (= #system/date"2019-03-23" (core/-eval expr eval-ctx nil nil))))) - (testing "an ELM year (only literals) always compiles to a DateYear" + (testing "an ELM year (only literals) always compiles to a System.Date" (satisfies-prop 100 (prop/for-all [year (s/gen :elm/literal-year)] - (instance? DateYear (c/compile {} year))))) + (system/date? (c/compile {} year))))) - (testing "an ELM year-month (only literals) always compiles to a DateYearMonth" + (testing "an ELM year-month (only literals) always compiles to a System.Date" (satisfies-prop 100 (prop/for-all [year-month (s/gen :elm/literal-year-month)] - (instance? DateYearMonth (c/compile {} year-month))))) + (system/date? (c/compile {} year-month))))) (testing "an ELM date (only literals) always compiles to something implementing Temporal" (satisfies-prop 100 (prop/for-all [date (s/gen :elm/literal-date)] - (instance? Temporal (c/compile {} date)))))) + (instance? Temporal (c/compile {} date))))) + + (testing "form and static" + (let [compile-ctx {:library + {:parameters + {:def + [{:name "year"} + {:name "month"} + {:name "day"}]}}}] + + (testing "year" + (let [elm #elm/date [#elm/parameter-ref "year"] + expr (c/compile compile-ctx elm)] + + (is (= '(date (param-ref "year")) (core/-form expr))) + + (is (false? (core/-static expr))))) + + (testing "year-month" + (let [elm #elm/date [#elm/parameter-ref "year" + #elm/parameter-ref "month"] + expr (c/compile compile-ctx elm)] + + (is (= '(date (param-ref "year") (param-ref "month")) + (core/-form expr))) + + (is (false? (core/-static expr))))) + + (testing "date" + (let [elm #elm/date [#elm/parameter-ref "year" + #elm/parameter-ref "month" + #elm/parameter-ref "day"] + expr (c/compile compile-ctx elm)] + + (is (= '(date (param-ref "year") (param-ref "month") (param-ref "day")) + (core/-form expr))) + + (is (false? (core/-static expr)))))))) ;; 18.7. DateFrom @@ -198,6 +236,8 @@ (tu/testing-unary-null elm/date-from) + (tu/testing-unary-dynamic elm/date-from) + (tu/testing-unary-form elm/date-from)) @@ -327,7 +367,7 @@ (are [elm] (thrown? Exception (c/compile {} elm)) #elm/date-time"10000-12-31T23:59:59.999")) - (testing "with offset" + (testing "with timezone offset" (are [elm res] (= res (core/-eval (c/compile {} elm) {:now tu/now} nil nil)) #elm/date-time[#elm/integer "2019" #elm/integer "3" #elm/integer "23" #elm/integer "12" #elm/integer "13" #elm/integer "14" #elm/integer "0" @@ -359,17 +399,178 @@ #elm/decimal "7"] (system/date-time 2012 3 10 3 20 0 999))) - (testing "with decimal offset" + (testing "with decimal timezone offset" (are [elm res] (= res (core/-eval (c/compile {} elm) {:now tu/now} nil nil)) #elm/date-time[#elm/integer "2019" #elm/integer "3" #elm/integer "23" #elm/integer "12" #elm/integer "13" #elm/integer "14" #elm/integer "0" #elm/decimal "1.5"] (system/date-time 2019 3 23 10 43 14))) - (testing "an ELM date-time (only literals) always evaluates to something implementing Temporal" + (testing "an ELM date-time (only literals) always evaluates to a System.DateTime" (satisfies-prop 100 (prop/for-all [date-time (s/gen :elm/literal-date-time)] - (instance? Temporal (core/-eval (c/compile {} date-time) {:now tu/now} nil nil)))))) + (system/date-time? (core/-eval (c/compile {} date-time) {:now tu/now} nil nil))))) + + (testing "form and static" + (let [compile-ctx {:library + {:parameters + {:def + [{:name "year"} + {:name "month"} + {:name "day"} + {:name "hour"} + {:name "minute"} + {:name "second"} + {:name "millisecond"} + {:name "timezone-offset"}]}}}] + + (testing "year" + (let [elm #elm/date-time [#elm/parameter-ref "year"] + expr (c/compile compile-ctx elm)] + + (is (= '(date-time (param-ref "year")) (core/-form expr))) + + (is (false? (core/-static expr))))) + + (testing "year-month" + (let [elm #elm/date-time [#elm/parameter-ref "year" + #elm/parameter-ref "month"] + expr (c/compile compile-ctx elm)] + + (is (= '(date-time (param-ref "year") (param-ref "month")) + (core/-form expr))) + + (is (false? (core/-static expr))))) + + (testing "date" + (let [elm #elm/date-time [#elm/parameter-ref "year" + #elm/parameter-ref "month" + #elm/parameter-ref "day"] + expr (c/compile compile-ctx elm)] + + (is (= '(date-time (param-ref "year") (param-ref "month") + (param-ref "day")) + (core/-form expr))) + + (is (false? (core/-static expr))))) + + (testing "with timezone offset" + (testing "All Static" + (let [elm #elm/date-time [#elm/integer "1" + #elm/integer "2" + #elm/integer "3" + #elm/integer "4" + #elm/integer "5" + #elm/integer "6" + #elm/integer "7" + #elm/integer "8"] + expr (c/compile compile-ctx elm)] + + (is (= '(date-time 1 2 3 4 5 6 7 8) (core/-form expr))) + + (is (false? (core/-static expr))))) + + (testing "Offset Static" + (let [elm #elm/date-time [#elm/parameter-ref "year" + #elm/parameter-ref "month" + #elm/parameter-ref "day" + #elm/parameter-ref "hour" + #elm/parameter-ref "minute" + #elm/parameter-ref "second" + #elm/parameter-ref "millisecond" + #elm/integer "1"] + expr (c/compile compile-ctx elm)] + + (is (= '(date-time (param-ref "year") (param-ref "month") + (param-ref "day") (param-ref "hour") + (param-ref "minute") (param-ref "second") + (param-ref "millisecond") 1) + (core/-form expr))) + + (is (false? (core/-static expr))))) + + (testing "Dynamic" + (let [elm #elm/date-time [#elm/parameter-ref "year" + #elm/parameter-ref "month" + #elm/parameter-ref "day" + #elm/parameter-ref "hour" + #elm/parameter-ref "minute" + #elm/parameter-ref "second" + #elm/parameter-ref "millisecond" + #elm/parameter-ref "timezone-offset"] + expr (c/compile compile-ctx elm)] + + (is (= '(date-time (param-ref "year") (param-ref "month") + (param-ref "day") (param-ref "hour") + (param-ref "minute") (param-ref "second") + (param-ref "millisecond") + (param-ref "timezone-offset")) + (core/-form expr))) + + (is (false? (core/-static expr)))))) + + (testing "without timezone offset" + (testing "hour" + (let [elm #elm/date-time [#elm/parameter-ref "year" + #elm/parameter-ref "month" + #elm/parameter-ref "day" + #elm/parameter-ref "hour"] + expr (c/compile compile-ctx elm)] + + (is (= '(date-time (param-ref "year") (param-ref "month") + (param-ref "day") (param-ref "hour") 0 0 0) + (core/-form expr))) + + (is (false? (core/-static expr))))) + + (testing "minute" + (let [elm #elm/date-time [#elm/parameter-ref "year" + #elm/parameter-ref "month" + #elm/parameter-ref "day" + #elm/parameter-ref "hour" + #elm/parameter-ref "minute"] + expr (c/compile compile-ctx elm)] + + (is (= '(date-time (param-ref "year") (param-ref "month") + (param-ref "day") (param-ref "hour") + (param-ref "minute") 0 0) + (core/-form expr))) + + (is (false? (core/-static expr))))) + + (testing "second" + (let [elm #elm/date-time [#elm/parameter-ref "year" + #elm/parameter-ref "month" + #elm/parameter-ref "day" + #elm/parameter-ref "hour" + #elm/parameter-ref "minute" + #elm/parameter-ref "second"] + expr (c/compile compile-ctx elm)] + + (is (= '(date-time (param-ref "year") (param-ref "month") + (param-ref "day") (param-ref "hour") + (param-ref "minute") (param-ref "second") 0) + (core/-form expr))) + + (is (false? (core/-static expr))))) + + (testing "millisecond" + (let [elm #elm/date-time [#elm/parameter-ref "year" + #elm/parameter-ref "month" + #elm/parameter-ref "day" + #elm/parameter-ref "hour" + #elm/parameter-ref "minute" + #elm/parameter-ref "second" + #elm/parameter-ref "millisecond"] + expr (c/compile compile-ctx elm)] + + (is (= '(date-time (param-ref "year") (param-ref "month") + (param-ref "day") (param-ref "hour") + (param-ref "minute") (param-ref "second") + (param-ref "millisecond")) + (core/-form expr))) + + (is (false? (core/-static expr))))))))) ;; 18.9. DateTimeComponentFrom @@ -401,6 +602,9 @@ (are [x precision res] (= res (eval (compile elm/date-time x precision))) "2019-04-17T12:48" "Hour" 12)) + (tu/testing-unary-precision-dynamic elm/date-time-component-from "Year" "Month" + "Day" "Hour" "Minute" "Second" "Millisecond") + (tu/testing-unary-precision-form elm/date-time-component-from "Year" "Month" "Day" "Hour" "Minute" "Second" "Millisecond")) @@ -471,6 +675,8 @@ "2018-01" "2018-01" "Day" "2018-01-01" "2018-01-01" "Hour")))) + (tu/testing-binary-precision-dynamic elm/difference-between "Year" "Month" "Day") + (tu/testing-binary-precision-form elm/difference-between "Year" "Month" "Day")) @@ -502,8 +708,8 @@ (let [compile (partial tu/compile-binop-precision elm/duration-between)] (testing "Year precision" - (doseq [op-xtor [elm/date elm/date-time]] - (are [x y res] (= res (compile op-xtor x y "Year")) + (doseq [op-ctor [elm/date elm/date-time]] + (are [x y res] (= res (compile op-ctor x y "Year")) "2018" "2019" 1 "2018" "2017" -1 "2018" "2018" 0))) @@ -539,6 +745,8 @@ "2018-01" "2018-01" "Day" "2018-01-01" "2018-01-01" "Hour")))) + (tu/testing-binary-precision-dynamic elm/duration-between "Year" "Month" "Day") + (tu/testing-binary-precision-form elm/duration-between "Year" "Month" "Day")) @@ -646,6 +854,8 @@ "2019-04-17" "2019-04-17" true "2019-04-17" "2019-04-18" true))) + (tu/testing-binary-precision-dynamic elm/same-as) + (tu/testing-binary-precision-form elm/same-as)) @@ -748,6 +958,8 @@ "2019-04" "2019-04" true "2019-04" "2019-03" true))) + (tu/testing-binary-precision-dynamic elm/same-or-before) + (tu/testing-binary-precision-form elm/same-or-before)) @@ -850,6 +1062,8 @@ "2019-04" "2019-04" true "2019-04" "2019-05" true))) + (tu/testing-binary-precision-dynamic elm/same-or-after) + (tu/testing-binary-precision-form elm/same-or-after)) @@ -923,7 +1137,59 @@ (testing "an ELM time (only literals) always compiles to a LocalTime" (satisfies-prop 100 (prop/for-all [time (s/gen :elm/time)] - (date-time/local-time? (c/compile {} time)))))) + (date-time/local-time? (c/compile {} time))))) + + (testing "form and static" + (let [compile-ctx {:library + {:parameters + {:def + [{:name "hour"} + {:name "minute"} + {:name "second"} + {:name "millisecond"}]}}}] + + (testing "hour" + (let [elm #elm/time [#elm/parameter-ref "hour"] + expr (c/compile compile-ctx elm)] + + (is (= '(time (param-ref "hour")) (core/-form expr))) + + (is (false? (core/-static expr))))) + + (testing "minute" + (let [elm #elm/time [#elm/parameter-ref "hour" + #elm/parameter-ref "minute"] + expr (c/compile compile-ctx elm)] + + (is (= '(time (param-ref "hour") (param-ref "minute")) + (core/-form expr))) + + (is (false? (core/-static expr))))) + + (testing "second" + (let [elm #elm/time [#elm/parameter-ref "hour" + #elm/parameter-ref "minute" + #elm/parameter-ref "second"] + expr (c/compile compile-ctx elm)] + + (is (= '(time (param-ref "hour") (param-ref "minute") + (param-ref "second")) + (core/-form expr))) + + (is (false? (core/-static expr))))) + + (testing "millisecond" + (let [elm #elm/time [#elm/parameter-ref "hour" + #elm/parameter-ref "minute" + #elm/parameter-ref "second" + #elm/parameter-ref "millisecond"] + expr (c/compile compile-ctx elm)] + + (is (= '(time (param-ref "hour") (param-ref "minute") + (param-ref "second") (param-ref "millisecond")) + (core/-form expr))) + + (is (false? (core/-static expr)))))))) ;; 18.21. TimeOfDay @@ -932,8 +1198,12 @@ ;; associated with the evaluation request. See the Now operator for more ;; information on the rationale for defining the TimeOfDay operator in this way. (deftest compile-time-of-day-test - (are [res] (= res (core/-eval (c/compile {} {:type "TimeOfDay"}) {:now tu/now} nil nil)) - (time/local-time tu/now))) + (are [res] (= res (core/-eval (c/compile {} elm/time-of-day) {:now tu/now} nil nil)) + (time/local-time tu/now)) + + (tu/testing-constant-dynamic elm/time-of-day) + + (tu/testing-constant-form elm/time-of-day)) ;; 18.22. Today @@ -946,4 +1216,6 @@ (are [res] (= res (core/-eval (c/compile {} elm/today) {:now tu/now} nil nil)) (DateDate/fromLocalDate (.toLocalDate ^OffsetDateTime tu/now))) + (tu/testing-constant-dynamic elm/today) + (tu/testing-constant-form elm/today)) diff --git a/modules/cql/test/blaze/elm/compiler/external_data_test.clj b/modules/cql/test/blaze/elm/compiler/external_data_test.clj index 9fc175b08..1c96b7e4b 100644 --- a/modules/cql/test/blaze/elm/compiler/external_data_test.clj +++ b/modules/cql/test/blaze/elm/compiler/external_data_test.clj @@ -5,24 +5,30 @@ https://cql.hl7.org/04-logicalspecification.html." (:require [blaze.anomaly :as ba] + [blaze.cql-translator :as t] [blaze.db.api :as d] [blaze.db.api-stub :refer [mem-node-config with-system-data]] [blaze.elm.compiler :as c] [blaze.elm.compiler.core :as core] - [blaze.elm.compiler.external-data] - [blaze.elm.compiler.test-util :as tu] + [blaze.elm.compiler.external-data :as ed] + [blaze.elm.compiler.external-data-spec] + [blaze.elm.compiler.library :as library] + [blaze.elm.compiler.test-util :as tu :refer [has-form]] + [blaze.elm.expression :as expr] + [blaze.elm.expression-spec] + [blaze.elm.expression.cache :as-alias expr-cache] [blaze.fhir.spec :as fhir-spec] [blaze.fhir.spec.type] - [blaze.test-util :refer [with-system]] + [blaze.module.test-util :refer [with-system]] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [deftest is testing]] [cognitect.anomalies :as anom] [juxt.iota :refer [given]]) (:import - [blaze.elm.compiler.external_data - WithRelatedContextQueryRetrieveExpression])) + [java.time OffsetDateTime])) +(set! *warn-on-reflection* true) (st/instrument) (tu/instrument-compile) @@ -37,6 +43,22 @@ (test/use-fixtures :each fixture) +(defn- eval-context [db] + {:db db :now (OffsetDateTime/now)}) + + +(defn- resource [db type id] + (ed/mk-resource db (d/resource-handle db type id))) + + +(deftest resource-test + (testing "toString" + (with-system-data [{:blaze.db/keys [node]} mem-node-config] + [[[:put {:fhir/type :fhir/Patient :id "0"}]]] + + (is (= "Patient[id = 0, t = 1]" (str (resource (d/db node) "Patient" "0"))))))) + + ;; 11.1. Retrieve ;; ;; All access to external data within ELM is represented by Retrieve expressions. @@ -73,22 +95,24 @@ :library {}} expr (c/compile context tu/patient-retrieve-elm) db (d/db node) - patient (d/resource-handle db "Patient" "0")] + patient (resource db "Patient" "0")] (testing "eval" - (given (core/-eval expr {:db db} patient nil) + (given (expr/eval (eval-context db) expr patient) [0 fhir-spec/fhir-type] := :fhir/Patient [0 :id] := "0")) + (testing "expression is dynamic" + (is (false? (core/-static expr)))) + (testing "form" - (is (= '(retrieve-resource) (core/-form expr))))))) + (has-form expr '(retrieve-resource)))))) (testing "Observation" (with-system-data [{:blaze.db/keys [node]} mem-node-config] [[[:put {:fhir/type :fhir/Patient :id "0"}] [:put {:fhir/type :fhir/Observation :id "1" - :subject - #fhir/Reference{:reference "Patient/0"}}]]] + :subject #fhir/Reference{:reference "Patient/0"}}]]] (let [context {:node node @@ -96,22 +120,24 @@ :library {}} expr (c/compile context #elm/retrieve{:type "Observation"}) db (d/db node) - patient (d/resource-handle db "Patient" "0")] + patient (resource db "Patient" "0")] (testing "eval" - (given (core/-eval expr {:db db} patient nil) + (given (expr/eval (eval-context db) expr patient) [0 fhir-spec/fhir-type] := :fhir/Observation [0 :id] := "1")) + (testing "expression is dynamic" + (is (false? (core/-static expr)))) + (testing "form" - (is (= '(compartment-list-retrieve "Observation") (core/-form expr)))))) + (has-form expr '(retrieve "Observation"))))) (testing "with one code" (with-system-data [{:blaze.db/keys [node]} mem-node-config] [[[:put {:fhir/type :fhir/Patient :id "0"}] [:put {:fhir/type :fhir/Observation :id "0" - :subject - #fhir/Reference{:reference "Patient/0"}}] + :subject #fhir/Reference{:reference "Patient/0"}}] [:put {:fhir/type :fhir/Observation :id "1" :code #fhir/CodeableConcept @@ -119,8 +145,7 @@ [#fhir/Coding {:system #fhir/uri"system-192253" :code #fhir/code"code-192300"}]} - :subject - #fhir/Reference{:reference "Patient/0"}}]]] + :subject #fhir/Reference{:reference "Patient/0"}}]]] (let [context {:node node @@ -136,24 +161,26 @@ "code-192300"]]} expr (c/compile context elm) db (d/db node) - patient (d/resource-handle db "Patient" "0")] + patient (resource db "Patient" "0")] (testing "eval" - (given (core/-eval expr {:db db} patient nil) + (given (expr/eval (eval-context db) expr patient) count := 1 [0 fhir-spec/fhir-type] := :fhir/Observation [0 :id] := "1")) + (testing "expression is dynamic" + (is (false? (core/-static expr)))) + (testing "form" - (is (= '(compartment-query-retrieve "Observation" [["code" "system-192253|code-192300"]]) - (core/-form expr))))))) + (has-form expr + '(retrieve "Observation" [["code" "system-192253|code-192300"]])))))) (testing "with two codes" (with-system-data [{:blaze.db/keys [node]} mem-node-config] [[[:put {:fhir/type :fhir/Patient :id "0"}] [:put {:fhir/type :fhir/Observation :id "0" - :subject - #fhir/Reference{:reference "Patient/0"}}] + :subject #fhir/Reference{:reference "Patient/0"}}] [:put {:fhir/type :fhir/Observation :id "1" :code #fhir/CodeableConcept @@ -161,8 +188,7 @@ [#fhir/Coding {:system #fhir/uri"system-192253" :code #fhir/code"code-192300"}]} - :subject - #fhir/Reference{:reference "Patient/0"}}] + :subject #fhir/Reference{:reference "Patient/0"}}] [:put {:fhir/type :fhir/Observation :id "2" :code #fhir/CodeableConcept @@ -170,8 +196,7 @@ [#fhir/Coding {:system #fhir/uri"system-192253" :code #fhir/code"code-140541"}]} - :subject - #fhir/Reference{:reference "Patient/0"}}]]] + :subject #fhir/Reference{:reference "Patient/0"}}]]] (let [context {:node node @@ -188,21 +213,32 @@ #elm/code ["sys-def-131750" "code-140541"]]} expr (c/compile context elm) db (d/db node) - patient (d/resource-handle db "Patient" "0")] + patient (resource db "Patient" "0")] - (given (core/-eval expr {:db db} patient nil) - count := 2 - [0 fhir-spec/fhir-type] := :fhir/Observation - [0 :id] := "1" - [1 fhir-spec/fhir-type] := :fhir/Observation - [1 :id] := "2")))) + (testing "eval" + (given (expr/eval (eval-context db) expr patient) + count := 2 + [0 fhir-spec/fhir-type] := :fhir/Observation + [0 :id] := "1" + [1 fhir-spec/fhir-type] := :fhir/Observation + [1 :id] := "2")) + + (testing "expression is dynamic" + (is (false? (core/-static expr)))) + + (testing "form" + (has-form expr + '(retrieve + "Observation" + [["code" + "system-192253|code-192300" + "system-192253|code-140541"]])))))) (testing "with one concept" (with-system-data [{:blaze.db/keys [node]} mem-node-config] [[[:put {:fhir/type :fhir/Patient :id "0"}] [:put {:fhir/type :fhir/Observation :id "0" - :subject - #fhir/Reference{:reference "Patient/0"}}] + :subject #fhir/Reference{:reference "Patient/0"}}] [:put {:fhir/type :fhir/Observation :id "1" :code #fhir/CodeableConcept @@ -210,8 +246,7 @@ [#fhir/Coding {:system #fhir/uri"system-192253" :code #fhir/code"code-192300"}]} - :subject - #fhir/Reference{:reference "Patient/0"}}] + :subject #fhir/Reference{:reference "Patient/0"}}] [:put {:fhir/type :fhir/Observation :id "2" :code #fhir/CodeableConcept @@ -219,8 +254,7 @@ [#fhir/Coding {:system #fhir/uri"system-192253" :code #fhir/code"code-140541"}]} - :subject - #fhir/Reference{:reference "Patient/0"}}]]] + :subject #fhir/Reference{:reference "Patient/0"}}]]] (let [context {:node node @@ -240,22 +274,33 @@ #elm/code ["sys-def-131750" "code-140541"]]]}} expr (c/compile context elm) db (d/db node) - patient (d/resource-handle db "Patient" "0")] + patient (resource db "Patient" "0")] - (given (core/-eval expr {:db db} patient nil) - count := 2 - [0 fhir-spec/fhir-type] := :fhir/Observation - [0 :id] := "1" - [1 fhir-spec/fhir-type] := :fhir/Observation - [1 :id] := "2")))))) + (testing "eval" + (given (expr/eval (eval-context db) expr patient) + count := 2 + [0 fhir-spec/fhir-type] := :fhir/Observation + [0 :id] := "1" + [1 fhir-spec/fhir-type] := :fhir/Observation + [1 :id] := "2")) + + (testing "expression is dynamic" + (is (false? (core/-static expr)))) + + (testing "form" + (has-form expr + '(retrieve + "Observation" + [["code" + "system-192253|code-192300" + "system-192253|code-140541"]])))))))) (testing "Specimen context" (testing "Patient" (with-system-data [{:blaze.db/keys [node]} mem-node-config] [[[:put {:fhir/type :fhir/Patient :id "0"}] [:put {:fhir/type :fhir/Specimen :id "0" - :subject - #fhir/Reference{:reference "Patient/0"}}]]] + :subject #fhir/Reference{:reference "Patient/0"}}]]] (let [context {:node node @@ -263,11 +308,19 @@ :library {}} expr (c/compile context tu/patient-retrieve-elm) db (d/db node) - specimen (d/resource-handle db "Specimen" "0")] + specimen (resource db "Specimen" "0")] + + (testing "eval" + (given (expr/eval (eval-context db) expr specimen) + [0 fhir-spec/fhir-type] := :fhir/Patient + [0 :id] := "0")) + + (testing "expression is dynamic" + (is (false? (core/-static expr)))) - (given (core/-eval expr {:db db} specimen nil) - [0 fhir-spec/fhir-type] := :fhir/Patient - [0 :id] := "0"))))) + (testing "form" + (has-form expr + '(retrieve (Specimen) "Patient"))))))) (testing "Unfiltered context" (testing "Medication" @@ -295,10 +348,18 @@ expr (c/compile context elm) db (d/db node)] - (given (core/-eval expr {:db db} nil nil) - count := 1 - [0 fhir-spec/fhir-type] := :fhir/Medication - [0 :id] := "0")))) + (testing "eval" + (given (expr/eval (eval-context db) expr nil) + count := 1 + [0 fhir-spec/fhir-type] := :fhir/Medication + [0 :id] := "0")) + + (testing "expression is dynamic" + (is (false? (core/-static expr)))) + + (testing "form" + (has-form expr + '(retrieve "Medication" [["code" "system-225806|code-225809"]])))))) (testing "unknown code property" (with-system [{:blaze.db/keys [node]} mem-node-config] @@ -321,23 +382,93 @@ ::anom/message := "The search-param with code `foo` and type `Medication` was not found."))))) (testing "with related context" + (testing "without code" + (with-system-data [{:blaze.db/keys [node]} mem-node-config] + [[[:put {:fhir/type :fhir/Patient :id "0"}] + [:put {:fhir/type :fhir/Observation :id "0" + :subject #fhir/Reference{:reference "Patient/0"}}]]] + + (let [library (t/translate + "library test + using FHIR version '4.0.0' + include FHIRHelpers version '4.0.0' + + context Patient + + define \"name-133756\": + singleton from ([Patient]) + + define InInitialPopulation: + [\"name-133756\" -> Observation] + ") + compile-context {::expr-cache/enabled? false} + {:keys [expression-defs]} (library/compile-library + node library compile-context) + db (d/db node) + patient (resource db "Patient" "0") + eval-context (assoc (eval-context db) :expression-defs expression-defs) + expr (:expression (get expression-defs "InInitialPopulation"))] + + (testing "eval" + (given (expr/eval eval-context expr patient) + count := 1 + [0 fhir-spec/fhir-type] := :fhir/Observation + [0 :id] := "0")) + + (testing "expression is dynamic" + (is (false? (core/-static expr)))) + + (testing "form" + (has-form expr '(retrieve (expr-ref "name-133756") "Observation")))))) + (testing "with pre-compiled database query" - (with-system [{:blaze.db/keys [node]} mem-node-config] - (let [library {:codeSystems - {:def [{:name "sys-def-174848" :id "system-174915"}]} - :statements - {:def - [{:type "ExpressionDef" - :name "name-174207" - :resultTypeName "{http://hl7.org/fhir}Patient"}]}} - elm #elm/retrieve - {:type "Observation" - :context #elm/expression-ref "name-174207" - :codes #elm/list [#elm/code ["sys-def-174848" - "code-174911"]]} - expr (c/compile {:node node :library library} elm)] - (given expr - type := WithRelatedContextQueryRetrieveExpression)))) + (with-system-data [{:blaze.db/keys [node]} mem-node-config] + [[[:put {:fhir/type :fhir/Patient :id "0"}] + [:put {:fhir/type :fhir/Observation :id "0" + :code + #fhir/CodeableConcept + {:coding + [#fhir/Coding + {:system #fhir/uri"system-133620" + :code #fhir/code"code-133657"}]} + :subject #fhir/Reference{:reference "Patient/0"}}]]] + + (let [library (t/translate + "library test + using FHIR version '4.0.0' + include FHIRHelpers version '4.0.0' + + codesystem sys: 'system-133620' + + context Patient + + define \"name-133730\": + singleton from ([Patient]) + + define InInitialPopulation: + [\"name-133730\" -> Observation: Code 'code-133657' from sys] + ") + compile-context {::expr-cache/enabled? false} + {:keys [expression-defs]} (library/compile-library + node library compile-context) + db (d/db node) + patient (resource db "Patient" "0") + eval-context (assoc (eval-context db) :expression-defs expression-defs) + expr (:expression (get expression-defs "InInitialPopulation"))] + + (testing "eval" + (given (expr/eval eval-context expr patient) + count := 1 + [0 fhir-spec/fhir-type] := :fhir/Observation + [0 :id] := "0")) + + (testing "expression is dynamic" + (is (false? (core/-static expr)))) + + (testing "form" + (has-form expr + '(retrieve (expr-ref "name-133730") "Observation" + [["code" "system-133620|code-133657"]])))))) (testing "unknown code property" (with-system [{:blaze.db/keys [node]} mem-node-config] @@ -354,6 +485,7 @@ :codes #elm/list [#elm/code ["sys-def-174848" "code-174911"]] :code-property "foo"}] + (given (ba/try-anomaly (c/compile {:node node :library library} elm)) ::anom/category := ::anom/not-found ::anom/message := "The search-param with code `foo` and type `Observation` was not found."))))) diff --git a/modules/cql/test/blaze/elm/compiler/interval_operators_test.clj b/modules/cql/test/blaze/elm/compiler/interval_operators_test.clj index 8d7e77a58..d65cc4e17 100644 --- a/modules/cql/test/blaze/elm/compiler/interval_operators_test.clj +++ b/modules/cql/test/blaze/elm/compiler/interval_operators_test.clj @@ -6,12 +6,14 @@ (:require [blaze.elm.compiler :as c] [blaze.elm.compiler.core :as core] + [blaze.elm.compiler.core-spec] [blaze.elm.compiler.interval-operators] [blaze.elm.compiler.test-util :as tu] [blaze.elm.decimal :as decimal] [blaze.elm.interval :refer [interval]] [blaze.elm.literal :as elm] [blaze.elm.literal-spec] + [blaze.test-util :refer [given-thrown]] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [are deftest testing]])) @@ -249,6 +251,8 @@ "2019-04-17" "2019-04-17" false "2019-04-17" "2019-04-18" false))) + (tu/testing-binary-precision-dynamic elm/after) + (tu/testing-binary-precision-form elm/after)) @@ -386,6 +390,8 @@ "2019-04-17" "2019-04-17" false "2019-04-17" "2019-04-16" false))) + (tu/testing-binary-precision-dynamic elm/before) + (tu/testing-binary-precision-form elm/before)) @@ -444,6 +450,8 @@ {:type "Null"} [(interval #system/date-time"2012-01-01" #system/date-time"2012-05-25")])) + (tu/testing-binary-dynamic elm/collapse) + (tu/testing-binary-form elm/collapse)) @@ -490,6 +498,8 @@ (tu/testing-binary-null elm/contains #elm/list [] #elm/integer "1")) + (tu/testing-binary-precision-dynamic elm/contains) + (tu/testing-binary-precision-form elm/contains)) @@ -521,6 +531,8 @@ (tu/testing-unary-null elm/end) + (tu/testing-unary-dynamic elm/end) + (tu/testing-unary-form elm/end)) @@ -548,6 +560,8 @@ (tu/testing-binary-null elm/ends interval-zero) + (tu/testing-binary-dynamic elm/ends) + (tu/testing-binary-precision-form elm/ends)) @@ -600,6 +614,8 @@ (tu/testing-binary-null elm/except interval-zero)) + (tu/testing-binary-dynamic elm/except) + (tu/testing-binary-form elm/except)) @@ -694,6 +710,8 @@ (tu/testing-binary-null elm/includes interval-zero)) + (tu/testing-binary-precision-dynamic elm/includes) + (tu/testing-binary-precision-form elm/includes)) @@ -759,6 +777,8 @@ (tu/testing-binary-null elm/intersect interval-zero)) + (tu/testing-binary-dynamic elm/intersect) + (tu/testing-binary-form elm/intersect)) @@ -792,6 +812,8 @@ (tu/testing-binary-null elm/meets-before interval-zero) + (tu/testing-binary-precision-dynamic elm/meets-before) + (tu/testing-binary-precision-form elm/meets-before)) @@ -817,6 +839,8 @@ (tu/testing-binary-null elm/meets-after interval-zero) + (tu/testing-binary-precision-dynamic elm/meets-after) + (tu/testing-binary-precision-form elm/meets-after)) @@ -872,6 +896,8 @@ (tu/testing-binary-null elm/overlaps interval-zero) + (tu/testing-binary-precision-dynamic elm/overlaps) + (tu/testing-binary-precision-form elm/overlaps)) @@ -897,13 +923,37 @@ ;; ;; If the source interval is null, the result is null. (deftest compile-point-from-test - (testing "Integer" - (are [x res] (= res (tu/compile-unop elm/point-from elm/interval x)) - [#elm/integer "1" #elm/integer "1"] 1 - [#elm/integer "2" #elm/integer "2"] 2)) + (testing "Static" + (testing "Integer" + (are [x res] (= res (tu/compile-unop elm/point-from elm/interval x)) + [#elm/integer "1" #elm/integer "1"] 1 + [#elm/integer "2" #elm/integer "2"] 2) + + (given-thrown (tu/compile-unop elm/point-from + (tu/with-locator elm/interval "locator-214950") + [#elm/integer "1" #elm/integer "2"]) + :message := "Invalid non-unit interval in `PointFrom` expression at locator-214950." + [:expression :type] := "PointFrom" + [:expression :operand :type] := "Interval" + [:expression :operand :locator] := "locator-214950"))) + + (testing "Dynamic" + (testing "Integer" + (are [elm res] (= res (tu/dynamic-compile-eval elm)) + #elm/point-from #elm/interval [#elm/integer "1" #elm/parameter-ref "1"] 1 + #elm/point-from #elm/interval [#elm/integer "2" #elm/parameter-ref "2"] 2) + + (given-thrown (tu/dynamic-compile-eval (elm/point-from ((tu/with-locator elm/interval "locator-161410") + [#elm/integer "1" #elm/parameter-ref "2"]))) + :message := "Invalid non-unit interval in `PointFrom` expression at locator-161410." + [:expression :type] := "PointFrom" + [:expression :operand :type] := "Interval" + [:expression :operand :locator] := "locator-161410"))) (tu/testing-unary-null elm/point-from) + (tu/testing-unary-dynamic elm/point-from) + (tu/testing-unary-form elm/point-from)) @@ -937,6 +987,8 @@ (tu/testing-binary-null elm/proper-contains interval-zero)) + (tu/testing-binary-precision-dynamic elm/proper-contains) + (tu/testing-binary-precision-form elm/proper-contains)) @@ -978,6 +1030,8 @@ (tu/testing-binary-null elm/proper-includes interval-zero)) + (tu/testing-binary-precision-dynamic elm/proper-includes) + (tu/testing-binary-precision-form elm/proper-includes)) @@ -1032,6 +1086,8 @@ (tu/testing-unary-null elm/start) + (tu/testing-unary-dynamic elm/start) + (tu/testing-unary-form elm/start)) @@ -1059,6 +1115,8 @@ (tu/testing-binary-null elm/starts interval-zero) + (tu/testing-binary-precision-dynamic elm/starts) + (tu/testing-binary-precision-form elm/starts)) @@ -1095,6 +1153,8 @@ (tu/testing-binary-null elm/union interval-zero)) + (tu/testing-binary-dynamic elm/union) + (tu/testing-binary-form elm/union)) @@ -1114,4 +1174,6 @@ (tu/testing-unary-null elm/width) + (tu/testing-unary-dynamic elm/width) + (tu/testing-unary-form elm/width)) diff --git a/modules/cql/test/blaze/elm/compiler/library_test.clj b/modules/cql/test/blaze/elm/compiler/library_test.clj index e7595dd43..9186742c9 100644 --- a/modules/cql/test/blaze/elm/compiler/library_test.clj +++ b/modules/cql/test/blaze/elm/compiler/library_test.clj @@ -2,11 +2,12 @@ (:require [blaze.cql-translator :as t] [blaze.db.api-stub :refer [mem-node-config]] - [blaze.elm.compiler :as compiler] + [blaze.elm.compiler :as c] [blaze.elm.compiler.library :as library] [blaze.elm.compiler.library-spec] [blaze.fhir.spec.type.system] - [blaze.test-util :refer [with-system]] + [blaze.module.test-util :refer [with-system]] + [blaze.test-util :as tu] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [deftest testing]] [cognitect.anomalies :as anom] @@ -16,13 +17,7 @@ (st/instrument) -(defn- fixture [f] - (st/instrument) - (f) - (st/unstrument)) - - -(test/use-fixtures :each fixture) +(test/use-fixtures :each tu/fixture) ;; 5.1. Library @@ -83,7 +78,7 @@ (with-system [{:blaze.db/keys [node]} mem-node-config] (given (library/compile-library node library {}) [:expression-defs "Gender" :context] := "Patient" - [:expression-defs "Gender" :expression compiler/form] := '(:gender (expr-ref "Patient")))))) + [:expression-defs "Gender" :expression c/form] := '(:gender (expr-ref "Patient")))))) (testing "one function" (let [library (t/translate "library Test @@ -95,7 +90,7 @@ (given (library/compile-library node library {}) [:expression-defs "InInitialPopulation" :context] := "Patient" [:expression-defs "InInitialPopulation" :resultTypeName] := "{http://hl7.org/fhir}AdministrativeGender" - [:expression-defs "InInitialPopulation" :expression compiler/form] := '(call "Gender" (expr-ref "Patient")) + [:expression-defs "InInitialPopulation" :expression c/form] := '(call "Gender" (expr-ref "Patient")) [:function-defs "Gender" :context] := "Patient" [:function-defs "Gender" :resultTypeName] := "{http://hl7.org/fhir}AdministrativeGender" [:function-defs "Gender" :function] :? fn?)))) @@ -110,7 +105,7 @@ (with-system [{:blaze.db/keys [node]} mem-node-config] (given (library/compile-library node library {}) [:expression-defs "InInitialPopulation" :context] := "Patient" - [:expression-defs "InInitialPopulation" :expression compiler/form] := '(call "Inc2" 1))))) + [:expression-defs "InInitialPopulation" :expression c/form] := '(call "Inc2" 1))))) (testing "with compile-time error" (testing "function" diff --git a/modules/cql/test/blaze/elm/compiler/list_operators_test.clj b/modules/cql/test/blaze/elm/compiler/list_operators_test.clj index 73ca2b0b6..39a530015 100644 --- a/modules/cql/test/blaze/elm/compiler/list_operators_test.clj +++ b/modules/cql/test/blaze/elm/compiler/list_operators_test.clj @@ -6,16 +6,20 @@ (:require [blaze.anomaly-spec] [blaze.elm.compiler :as c] + [blaze.elm.compiler-spec] [blaze.elm.compiler.core :as core] + [blaze.elm.compiler.core-spec] [blaze.elm.compiler.list-operators] - [blaze.elm.compiler.test-util :as tu] + [blaze.elm.compiler.test-util :as tu :refer [has-form]] + [blaze.elm.expression-spec] + [blaze.elm.expression.cache :as-alias expr-cache] [blaze.elm.literal :as elm] [blaze.elm.literal-spec] [blaze.elm.quantity :as quantity] [blaze.test-util :refer [satisfies-prop]] [clojure.spec.alpha :as s] [clojure.spec.test.alpha :as st] - [clojure.test :as test :refer [are deftest testing]] + [clojure.test :as test :refer [are deftest is testing]] [clojure.test.check.properties :as prop])) @@ -44,21 +48,27 @@ ;; ;; If any argument is null, the resulting list will have null for that element. (deftest compile-list-test - (are [elm res] (= res (core/-eval (c/compile {} elm) {} nil nil)) - #elm/list [] - [] + (testing "Static" + (are [elm res] (= res (c/compile {} elm)) + #elm/list [] [] + #elm/list [{:type "Null"}] [nil] + #elm/list [#elm/integer "1"] [1] + #elm/list [#elm/integer "1" {:type "Null"}] [1 nil] + #elm/list [#elm/integer "1" #elm/integer "2"] [1 2]) - #elm/list [{:type "Null"}] - [nil] + (testing "form" + (is (= [] (c/form (c/compile {} #elm/list [])))))) - #elm/list [#elm/integer "1"] - [1] + (testing "Dynamic" + (are [elm res] (= res (tu/dynamic-compile-eval elm)) + #elm/list [#elm/parameter-ref "nil"] [nil] + #elm/list [#elm/parameter-ref "1"] [1] + #elm/list [#elm/parameter-ref "1" #elm/parameter-ref "nil"] [1 nil] + #elm/list [#elm/parameter-ref "1" #elm/parameter-ref "2"] [1 2]) - #elm/list [#elm/integer "1" {:type "Null"}] - [1 nil] - - #elm/list [#elm/integer "1" #elm/integer "2"] - [1 2])) + (testing "form" + (let [expr (tu/dynamic-compile #elm/list [#elm/parameter-ref "x"])] + (has-form expr '(list (param-ref "x"))))))) ;; 20.2. Contains @@ -78,14 +88,22 @@ (testing "default scope" (satisfies-prop 100 (prop/for-all [x (s/gen int?)] - (= x (core/-eval (c/compile {} {:type "Current"}) {} nil x))))) + (= x (core/-eval (c/compile {} #elm/current nil) {} nil x)))) + + (testing "form" + (let [expr (c/compile {} #elm/current nil)] + (has-form expr 'current)))) (testing "named scope" (satisfies-prop 100 (prop/for-all [scope (s/gen string?) x (s/gen int?)] - (let [expr (c/compile {} {:type "Current" :scope scope})] - (= x (core/-eval expr {} nil {scope x}))))))) + (let [expr (c/compile {} (elm/current scope))] + (= x (core/-eval expr {} nil {scope x}))))) + + (testing "form" + (let [expr (c/compile {} #elm/current "x")] + (has-form expr '(current "x")))))) ;; 20.4. Distinct @@ -113,6 +131,8 @@ (tu/testing-unary-null elm/distinct) + (tu/testing-unary-dynamic elm/distinct) + (tu/testing-unary-form elm/distinct)) @@ -137,14 +157,25 @@ ;; ;; If the argument is null, the result is false. (deftest compile-exists-test - (are [list res] (= res (c/compile {} (elm/exists list))) - #elm/list [#elm/integer "1"] true - #elm/list [#elm/integer "1" #elm/integer "1"] true - #elm/list [] false + (testing "Static" + (are [list res] (= res (c/compile {} (elm/exists list))) + #elm/list [#elm/integer "1"] true + #elm/list [#elm/integer "1" #elm/integer "1"] true + #elm/list [{:type "Null"}] false + #elm/list [] false + + {:type "Null"} false)) - {:type "Null"} false) + (testing "Dynamic" + (are [list res] (= res (tu/dynamic-compile-eval (elm/exists list))) + #elm/list [#elm/parameter-ref "1"] true + #elm/list [#elm/parameter-ref "1" #elm/parameter-ref "1"] true + #elm/list [#elm/parameter-ref "nil"] false + #elm/list [] false - (tu/testing-unary-form elm/exists)) + {:type "Null"} false) + + (tu/testing-unary-form elm/exists))) ;; 20.9. Filter @@ -154,11 +185,46 @@ ;; ;; If the source argument is null, the result is null. (deftest compile-filter-test - (are [source condition res] (= res (core/-eval (c/compile {} {:type "Filter" :source source :condition condition :scope "A"}) {} nil nil)) - #elm/list [#elm/integer "1"] #elm/boolean "false" [] - #elm/list [#elm/integer "1"] #elm/equal [#elm/current "A" #elm/integer "1"] [1] + (testing "eval" + (let [eval #(core/-eval % {} nil nil)] + (testing "with scope" + (are [source condition res] (= res (eval (c/compile {} {:type "Filter" + :source source + :condition condition + :scope "A"}))) + #elm/list [#elm/integer "1"] #elm/boolean "false" [] + #elm/list [#elm/integer "1"] #elm/equal [#elm/current "A" #elm/integer "1"] [1] + + {:type "Null"} #elm/boolean "true" nil)) + + (testing "without scope" + (are [source condition res] (= res (eval (c/compile {} {:type "Filter" + :source source + :condition condition}))) + #elm/list [#elm/integer "1"] #elm/boolean "false" [] + #elm/list [#elm/integer "1"] #elm/equal [#elm/current nil #elm/integer "1"] [1] + + {:type "Null"} #elm/boolean "true" nil)))) + + (testing "form and static" + (testing "with scope" + (let [expr (tu/dynamic-compile {:type "Filter" + :source #elm/parameter-ref "x" + :condition #elm/parameter-ref "y" + :scope "A"})] - {:type "Null"} #elm/boolean "true" nil)) + (has-form expr '(filter (param-ref "x") (param-ref "y") "A")) + + (is (false? (core/-static expr))))) + + (testing "without scope" + (let [expr (tu/dynamic-compile {:type "Filter" + :source #elm/parameter-ref "x" + :condition #elm/parameter-ref "y"})] + + (has-form expr '(filter (param-ref "x") (param-ref "y"))) + + (is (false? (core/-static expr))))))) ;; 20.10. First @@ -169,11 +235,21 @@ ;; ;; If the argument is null, the result is null. (deftest compile-first-test - (are [source res] (= res (core/-eval (c/compile {} (elm/first source)) {} nil nil)) - #elm/list [#elm/integer "1"] 1 - #elm/list [#elm/integer "1" #elm/integer "2"] 1 + (testing "Static" + (are [source res] (= res (core/-eval (c/compile {} (elm/first source)) {} nil nil)) + #elm/list [#elm/integer "1"] 1 + #elm/list [#elm/integer "1" #elm/integer "2"] 1)) - {:type "Null"} nil)) + (testing "Dynamic" + (are [source res] (= res (tu/dynamic-compile-eval (elm/first source))) + #elm/parameter-ref "[1]" 1 + #elm/parameter-ref "[1 2]" 1)) + + (tu/testing-unary-null elm/first) + + (tu/testing-unary-dynamic elm/first) + + (tu/testing-unary-form elm/first)) ;; 20.11. Flatten @@ -192,6 +268,8 @@ (tu/testing-unary-null elm/flatten) + (tu/testing-unary-dynamic elm/flatten) + (tu/testing-unary-form elm/flatten)) @@ -207,18 +285,46 @@ ;; If the element argument evaluates to null for some item in the source list, ;; the resulting list will contain a null for that element. (deftest compile-for-each-test - (testing "Without scope" - (are [source element res] (= res (core/-eval (c/compile {} {:type "ForEach" :source source :element element}) {} nil nil)) - #elm/list [#elm/integer "1"] {:type "Null"} [nil] + (testing "eval" + (let [eval #(core/-eval % {} nil nil)] + (testing "with scope" + (are [source element res] (= res (eval (c/compile {} {:type "ForEach" + :source source + :element element + :scope "A"}))) + #elm/list [#elm/integer "1"] #elm/current "A" [1] + #elm/list [#elm/integer "1" #elm/integer "2"] #elm/add [#elm/current "A" #elm/integer "1"] [2 3] + + {:type "Null"} {:type "Null"} nil)) - {:type "Null"} {:type "Null"} nil)) + (testing "without scope" + (are [source element res] (= res (eval (c/compile {} {:type "ForEach" + :source source + :element element}))) + #elm/list [#elm/integer "1"] #elm/current nil [1] + #elm/list [#elm/integer "1" #elm/integer "2"] #elm/add [#elm/current nil #elm/integer "1"] [2 3] - (testing "With scope" - (are [source element res] (= res (core/-eval (c/compile {} {:type "ForEach" :source source :element element :scope "A"}) {} nil nil)) - #elm/list [#elm/integer "1"] #elm/current "A" [1] - #elm/list [#elm/integer "1" #elm/integer "2"] #elm/add [#elm/current "A" #elm/integer "1"] [2 3] + {:type "Null"} {:type "Null"} nil)))) - {:type "Null"} {:type "Null"} nil))) + (testing "form and static" + (testing "with scope" + (let [expr (tu/dynamic-compile {:type "ForEach" + :source #elm/parameter-ref "x" + :element #elm/parameter-ref "y" + :scope "A"})] + + (has-form expr '(for-each (param-ref "x") (param-ref "y") "A")) + + (is (false? (core/-static expr))))) + + (testing "without scope" + (let [expr (tu/dynamic-compile {:type "ForEach" + :source #elm/parameter-ref "x" + :element #elm/parameter-ref "y"})] + + (has-form expr '(for-each (param-ref "x") (param-ref "y"))) + + (is (false? (core/-static expr))))))) ;; 20.13. In @@ -249,7 +355,7 @@ ;; ;; If either argument is null, the result is null. (deftest compile-index-of-test - (are [source element res] (= res (core/-eval (c/compile {} {:type "IndexOf" :source source :element element}) {} nil nil)) + (are [source element res] (= res (core/-eval (c/compile {} (elm/index-of [source element])) {} nil nil)) #elm/list [] #elm/integer "1" -1 #elm/list [#elm/integer "1"] #elm/integer "1" 0 #elm/list [#elm/integer "1" #elm/integer "1"] #elm/integer "1" 0 @@ -257,7 +363,13 @@ #elm/list [] {:type "Null"} nil {:type "Null"} #elm/integer "1" nil - {:type "Null"} {:type "Null"} nil)) + {:type "Null"} {:type "Null"} nil) + + (tu/testing-binary-dynamic-null elm/index-of #elm/list [] #elm/integer "1") + + (tu/testing-binary-dynamic elm/index-of) + + (tu/testing-binary-form elm/index-of)) ;; 20.17. Intersect @@ -273,11 +385,21 @@ ;; ;; If the argument is null, the result is null. (deftest compile-last-test - (are [source res] (= res (core/-eval (c/compile {} {:type "Last" :source source}) {} nil nil)) - #elm/list [#elm/integer "1"] 1 - #elm/list [#elm/integer "1" #elm/integer "2"] 2 + (testing "Static" + (are [source res] (= res (core/-eval (c/compile {} (elm/last source)) {} nil nil)) + #elm/list [#elm/integer "1"] 1 + #elm/list [#elm/integer "1" #elm/integer "2"] 2)) + + (testing "Dynamic" + (are [source res] (= res (tu/dynamic-compile-eval (elm/last source))) + #elm/parameter-ref "[1]" 1 + #elm/parameter-ref "[1 2]" 2)) + + (tu/testing-unary-null elm/last) - {:type "Null"} nil)) + (tu/testing-unary-dynamic elm/last) + + (tu/testing-unary-form elm/last)) ;; 20.19. Not Equal @@ -337,7 +459,11 @@ (are [list] (thrown? Exception (core/-eval (c/compile {} (elm/singleton-from list)) {} nil nil)) #elm/list [#elm/integer "1" #elm/integer "1"]) - (tu/testing-unary-null elm/singleton-from)) + (tu/testing-unary-null elm/singleton-from) + + (tu/testing-unary-dynamic elm/singleton-from) + + (tu/testing-unary-form elm/singleton-from)) ;; 20.26. Slice @@ -366,7 +492,19 @@ {:type "Null"} #elm/integer "0" #elm/integer "0" nil - {:type "Null"} {:type "Null"} {:type "Null"} nil)) + {:type "Null"} {:type "Null"} {:type "Null"} nil) + + (let [expr (tu/dynamic-compile {:type "Slice" + :source #elm/parameter-ref "x" + :startIndex #elm/parameter-ref "y" + :endIndex #elm/parameter-ref "z"})] + + (testing "expression is dynamic" + (is (false? (core/-static expr)))) + + (testing "form" + (is (= '(slice (param-ref "x") (param-ref "y") (param-ref "z")) + (core/-form expr)))))) ;; 20.27. Sort @@ -387,7 +525,17 @@ #elm/list [#elm/integer "1" #elm/integer "2"] {:type "ByDirection" :direction "desc"} [2 1] - {:type "Null"} {:type "ByDirection" :direction "asc"} nil)) + {:type "Null"} {:type "ByDirection" :direction "asc"} nil) + + (let [expr (tu/dynamic-compile {:type "Sort" + :source #elm/parameter-ref "x" + :by [{:type "ByDirection" :direction "asc"}]})] + + (testing "expression is dynamic" + (is (false? (core/-static expr)))) + + (testing "form" + (is (= '(sort (param-ref "x") :asc) (core/-form expr)))))) ;; 20.28. Times @@ -447,6 +595,8 @@ (tu/testing-binary-null elm/times #elm/list[#elm/tuple{"name" #elm/string "hans"}]) + (tu/testing-binary-dynamic elm/times) + (tu/testing-binary-form elm/times)) diff --git a/modules/cql/test/blaze/elm/compiler/logical_operators_test.clj b/modules/cql/test/blaze/elm/compiler/logical_operators_test.clj index edfd657f6..87ae59d81 100644 --- a/modules/cql/test/blaze/elm/compiler/logical_operators_test.clj +++ b/modules/cql/test/blaze/elm/compiler/logical_operators_test.clj @@ -5,6 +5,7 @@ https://cql.hl7.org/04-logicalspecification.html." (:require [blaze.elm.compiler :as c] + [blaze.elm.compiler.core :as core] [blaze.elm.compiler.logical-operators] [blaze.elm.compiler.test-util :as tu] [blaze.elm.literal :as elm] @@ -72,54 +73,55 @@ #elm/parameter-ref "nil" #elm/parameter-ref "nil" nil)) (testing "form" - (let [compile-ctx# {:library {:parameters {:def [{:name "a"} {:name "b"}]}}}] - (are [x y form] (= form (c/form (c/compile compile-ctx# (elm/and [x y])))) - #elm/boolean "true" #elm/boolean "true" true - #elm/boolean "true" #elm/boolean "false" false - #elm/boolean "true" {:type "Null"} nil - #elm/boolean "true" #elm/parameter-ref "b" '(param-ref "b") - - #elm/boolean "false" #elm/boolean "true" false - #elm/boolean "false" #elm/boolean "false" false - #elm/boolean "false" {:type "Null"} false - #elm/boolean "false" #elm/parameter-ref "b" false + (are [x y form] (= form (c/form (tu/dynamic-compile (elm/and [x y])))) + #elm/boolean "true" #elm/boolean "true" true + #elm/boolean "true" #elm/boolean "false" false + #elm/boolean "true" {:type "Null"} nil + #elm/boolean "true" #elm/parameter-ref "b" '(param-ref "b") - {:type "Null"} #elm/boolean "true" nil - {:type "Null"} #elm/boolean "false" false - {:type "Null"} {:type "Null"} nil - {:type "Null"} #elm/parameter-ref "b" '(and nil (param-ref "b")) + #elm/boolean "false" #elm/boolean "true" false + #elm/boolean "false" #elm/boolean "false" false + #elm/boolean "false" {:type "Null"} false + #elm/boolean "false" #elm/parameter-ref "b" false - #elm/parameter-ref "a" #elm/boolean "true" '(param-ref "a") - #elm/parameter-ref "a" #elm/boolean "false" false - #elm/parameter-ref "a" {:type "Null"} '(and nil (param-ref "a")) - #elm/parameter-ref "a" #elm/parameter-ref "b" '(and (param-ref "a") (param-ref "b")))))) + {:type "Null"} #elm/boolean "true" nil + {:type "Null"} #elm/boolean "false" false + {:type "Null"} {:type "Null"} nil + {:type "Null"} #elm/parameter-ref "b" '(and nil (param-ref "b")) + #elm/parameter-ref "a" #elm/boolean "true" '(param-ref "a") + #elm/parameter-ref "a" #elm/boolean "false" false + #elm/parameter-ref "a" {:type "Null"} '(and nil (param-ref "a")) + #elm/parameter-ref "a" #elm/parameter-ref "b" '(and (param-ref "a") (param-ref "b")))) -;; 13.2. Implies -;; -;; The Implies operator returns the logical implication of its arguments. Note -;; that this operator is defined using 3-valued logic semantics. This means that -;; if the left operand evaluates to true, this operator returns the boolean -;; evaluation of the right operand. If the left operand evaluates to false, this -;; operator returns true. Otherwise, this operator returns true if the right -;; operand evaluates to true, and null otherwise. -;; -;; Note that implies may use short-circuit evaluation in the case that the first -;; operand evaluates to false. -(deftest compile-implies-test - (testing "Static" - (are [x y res] (= res (c/compile {} (elm/or [(elm/not x) y]))) + (testing "static" + (are [x y static] (identical? static (core/-static (tu/dynamic-compile (elm/and [x y])))) #elm/boolean "true" #elm/boolean "true" true - #elm/boolean "true" #elm/boolean "false" false - #elm/boolean "true" {:type "Null"} nil + #elm/boolean "true" #elm/boolean "false" true + #elm/boolean "true" {:type "Null"} true + #elm/boolean "true" #elm/parameter-ref "b" false #elm/boolean "false" #elm/boolean "true" true #elm/boolean "false" #elm/boolean "false" true #elm/boolean "false" {:type "Null"} true + #elm/boolean "false" #elm/parameter-ref "b" true {:type "Null"} #elm/boolean "true" true - {:type "Null"} #elm/boolean "false" nil - {:type "Null"} {:type "Null"} nil))) + {:type "Null"} #elm/boolean "false" true + {:type "Null"} {:type "Null"} true + {:type "Null"} #elm/parameter-ref "b" false + + #elm/parameter-ref "a" #elm/boolean "true" false + #elm/parameter-ref "a" #elm/boolean "false" true + #elm/parameter-ref "a" {:type "Null"} false + #elm/parameter-ref "a" #elm/parameter-ref "b" false))) + + +;; 13.2. Implies +;; +;; Normalized to (Or (Not x) y) +(deftest compile-implies-test + (tu/unsupported-binary-operand "Implies")) ;; 13.3. Not @@ -131,14 +133,16 @@ (testing "Static" (are [x res] (= res (c/compile {} (elm/not x))) #elm/boolean "true" false - #elm/boolean "false" true - {:type "Null"} nil)) + #elm/boolean "false" true)) (testing "Dynamic" (are [x res] (= res (tu/dynamic-compile-eval (elm/not x))) #elm/parameter-ref "true" false - #elm/parameter-ref "false" true - #elm/parameter-ref "nil" nil)) + #elm/parameter-ref "false" true)) + + (tu/testing-unary-null elm/not) + + (tu/testing-unary-dynamic elm/not) (tu/testing-unary-form elm/not)) @@ -186,27 +190,48 @@ #elm/parameter-ref "nil" #elm/parameter-ref "nil" nil)) (testing "form" - (let [compile-ctx# {:library {:parameters {:def [{:name "a"} {:name "b"}]}}}] - (are [x y form] (= form (c/form (c/compile compile-ctx# (elm/or [x y])))) - #elm/boolean "true" #elm/boolean "true" true - #elm/boolean "true" #elm/boolean "false" true - #elm/boolean "true" {:type "Null"} true - #elm/boolean "true" #elm/parameter-ref "b" true + (are [x y form] (= form (c/form (tu/dynamic-compile (elm/or [x y])))) + #elm/boolean "true" #elm/boolean "true" true + #elm/boolean "true" #elm/boolean "false" true + #elm/boolean "true" {:type "Null"} true + #elm/boolean "true" #elm/parameter-ref "b" true - #elm/boolean "false" #elm/boolean "true" true - #elm/boolean "false" #elm/boolean "false" false - #elm/boolean "false" {:type "Null"} nil - #elm/boolean "false" #elm/parameter-ref "b" '(param-ref "b") + #elm/boolean "false" #elm/boolean "true" true + #elm/boolean "false" #elm/boolean "false" false + #elm/boolean "false" {:type "Null"} nil + #elm/boolean "false" #elm/parameter-ref "b" '(param-ref "b") - {:type "Null"} #elm/boolean "true" true - {:type "Null"} #elm/boolean "false" nil - {:type "Null"} {:type "Null"} nil - {:type "Null"} #elm/parameter-ref "b" '(or nil (param-ref "b")) + {:type "Null"} #elm/boolean "true" true + {:type "Null"} #elm/boolean "false" nil + {:type "Null"} {:type "Null"} nil + {:type "Null"} #elm/parameter-ref "b" '(or nil (param-ref "b")) - #elm/parameter-ref "a" #elm/boolean "true" true - #elm/parameter-ref "a" #elm/boolean "false" '(param-ref "a") - #elm/parameter-ref "a" {:type "Null"} '(or nil (param-ref "a")) - #elm/parameter-ref "a" #elm/parameter-ref "b" '(or (param-ref "a") (param-ref "b")))))) + #elm/parameter-ref "a" #elm/boolean "true" true + #elm/parameter-ref "a" #elm/boolean "false" '(param-ref "a") + #elm/parameter-ref "a" {:type "Null"} '(or nil (param-ref "a")) + #elm/parameter-ref "a" #elm/parameter-ref "b" '(or (param-ref "a") (param-ref "b")))) + + (testing "static" + (are [x y static] (identical? static (core/-static (tu/dynamic-compile (elm/or [x y])))) + #elm/boolean "true" #elm/boolean "true" true + #elm/boolean "true" #elm/boolean "false" true + #elm/boolean "true" {:type "Null"} true + #elm/boolean "true" #elm/parameter-ref "b" true + + #elm/boolean "false" #elm/boolean "true" true + #elm/boolean "false" #elm/boolean "false" true + #elm/boolean "false" {:type "Null"} true + #elm/boolean "false" #elm/parameter-ref "b" false + + {:type "Null"} #elm/boolean "true" true + {:type "Null"} #elm/boolean "false" true + {:type "Null"} {:type "Null"} true + {:type "Null"} #elm/parameter-ref "b" false + + #elm/parameter-ref "a" #elm/boolean "true" true + #elm/parameter-ref "a" #elm/boolean "false" false + #elm/parameter-ref "a" {:type "Null"} false + #elm/parameter-ref "a" #elm/parameter-ref "b" false))) ;; 13.5. Xor @@ -255,24 +280,45 @@ #elm/parameter-ref "nil" #elm/parameter-ref "nil" nil)) (testing "form" - (let [compile-ctx# {:library {:parameters {:def [{:name "a"} {:name "b"}]}}}] - (are [x y form] (= form (c/form (c/compile compile-ctx# (elm/xor [x y])))) - #elm/boolean "true" #elm/boolean "true" false - #elm/boolean "true" #elm/boolean "false" true - #elm/boolean "true" {:type "Null"} nil - #elm/boolean "true" #elm/parameter-ref "b" '(not (param-ref "b")) - - #elm/boolean "false" #elm/boolean "true" true - #elm/boolean "false" #elm/boolean "false" false - #elm/boolean "false" {:type "Null"} nil - #elm/boolean "false" #elm/parameter-ref "b" '(param-ref "b") - - {:type "Null"} #elm/boolean "true" nil - {:type "Null"} #elm/boolean "false" nil - {:type "Null"} {:type "Null"} nil - {:type "Null"} #elm/parameter-ref "b" nil - - #elm/parameter-ref "a" #elm/boolean "true" '(not (param-ref "a")) - #elm/parameter-ref "a" #elm/boolean "false" '(param-ref "a") - #elm/parameter-ref "a" {:type "Null"} nil - #elm/parameter-ref "a" #elm/parameter-ref "b" '(xor (param-ref "a") (param-ref "b")))))) + (are [x y form] (= form (c/form (tu/dynamic-compile (elm/xor [x y])))) + #elm/boolean "true" #elm/boolean "true" false + #elm/boolean "true" #elm/boolean "false" true + #elm/boolean "true" {:type "Null"} nil + #elm/boolean "true" #elm/parameter-ref "b" '(not (param-ref "b")) + + #elm/boolean "false" #elm/boolean "true" true + #elm/boolean "false" #elm/boolean "false" false + #elm/boolean "false" {:type "Null"} nil + #elm/boolean "false" #elm/parameter-ref "b" '(param-ref "b") + + {:type "Null"} #elm/boolean "true" nil + {:type "Null"} #elm/boolean "false" nil + {:type "Null"} {:type "Null"} nil + {:type "Null"} #elm/parameter-ref "b" nil + + #elm/parameter-ref "a" #elm/boolean "true" '(not (param-ref "a")) + #elm/parameter-ref "a" #elm/boolean "false" '(param-ref "a") + #elm/parameter-ref "a" {:type "Null"} nil + #elm/parameter-ref "a" #elm/parameter-ref "b" '(xor (param-ref "a") (param-ref "b")))) + + (testing "static" + (are [x y static] (identical? static (core/-static (tu/dynamic-compile (elm/xor [x y])))) + #elm/boolean "true" #elm/boolean "true" true + #elm/boolean "true" #elm/boolean "false" true + #elm/boolean "true" {:type "Null"} true + #elm/boolean "true" #elm/parameter-ref "b" false + + #elm/boolean "false" #elm/boolean "true" true + #elm/boolean "false" #elm/boolean "false" true + #elm/boolean "false" {:type "Null"} true + #elm/boolean "false" #elm/parameter-ref "b" false + + {:type "Null"} #elm/boolean "true" true + {:type "Null"} #elm/boolean "false" true + {:type "Null"} {:type "Null"} true + {:type "Null"} #elm/parameter-ref "b" true + + #elm/parameter-ref "a" #elm/boolean "true" false + #elm/parameter-ref "a" #elm/boolean "false" false + #elm/parameter-ref "a" {:type "Null"} true + #elm/parameter-ref "a" #elm/parameter-ref "b" false))) diff --git a/modules/cql/test/blaze/elm/compiler/nullological_operators_test.clj b/modules/cql/test/blaze/elm/compiler/nullological_operators_test.clj index 7a73dc6c8..1e701182a 100644 --- a/modules/cql/test/blaze/elm/compiler/nullological_operators_test.clj +++ b/modules/cql/test/blaze/elm/compiler/nullological_operators_test.clj @@ -6,6 +6,7 @@ (:require [blaze.elm.compiler :as c] [blaze.elm.compiler.core :as core] + [blaze.elm.compiler.core-spec] [blaze.elm.compiler.test-util :as tu] [blaze.elm.literal :as elm] [blaze.elm.literal-spec] @@ -50,7 +51,13 @@ [#elm/integer "2"] 2 [#elm/list []] nil [{:type "Null"} #elm/list [#elm/string "a"]] ["a"] - [#elm/list [{:type "Null"} #elm/string "a"]] "a")) + [#elm/list [{:type "Null"} #elm/string "a"]] "a") + + (testing "expression is dynamic" + (are [elm] (false? (core/-static (tu/dynamic-compile (elm/coalesce elm)))) + [] + [{:type "Null"}] + [#elm/list []]))) ;; 14.3. IsFalse @@ -71,6 +78,8 @@ #elm/parameter-ref "false" true #elm/parameter-ref "nil" false)) + (tu/testing-unary-dynamic elm/is-false) + (tu/testing-unary-form elm/is-false)) @@ -92,6 +101,8 @@ #elm/parameter-ref "false" false #elm/parameter-ref "nil" true)) + (tu/testing-unary-dynamic elm/is-null) + (tu/testing-unary-form elm/is-null)) @@ -113,4 +124,6 @@ #elm/parameter-ref "false" false #elm/parameter-ref "nil" false)) + (tu/testing-unary-dynamic elm/is-true) + (tu/testing-unary-form elm/is-true)) diff --git a/modules/cql/test/blaze/elm/compiler/parameters_test.clj b/modules/cql/test/blaze/elm/compiler/parameters_test.clj index bcef1b140..665c5d23f 100644 --- a/modules/cql/test/blaze/elm/compiler/parameters_test.clj +++ b/modules/cql/test/blaze/elm/compiler/parameters_test.clj @@ -8,8 +8,9 @@ [blaze.elm.code-spec] [blaze.elm.compiler :as c] [blaze.elm.compiler.core :as core] + [blaze.elm.compiler.core-spec] [blaze.elm.compiler.parameters :refer [->ParameterRef]] - [blaze.elm.compiler.test-util :as tu] + [blaze.elm.compiler.test-util :as tu :refer [has-form]] [blaze.elm.literal] [blaze.elm.literal-spec] [clojure.spec.test.alpha :as st] @@ -47,7 +48,7 @@ (is (= (->ParameterRef "parameter-def-101820") expr)) (testing "form" - (is (= '(param-ref "parameter-def-101820") (core/-form expr)))))) + (has-form expr '(param-ref "parameter-def-101820"))))) (testing "definition not found" (let [context {:library {}}] diff --git a/modules/cql/test/blaze/elm/compiler/queries_test.clj b/modules/cql/test/blaze/elm/compiler/queries_test.clj index cae3b96d6..57bf10167 100644 --- a/modules/cql/test/blaze/elm/compiler/queries_test.clj +++ b/modules/cql/test/blaze/elm/compiler/queries_test.clj @@ -11,8 +11,9 @@ [blaze.elm.code-spec] [blaze.elm.compiler :as c] [blaze.elm.compiler.core :as core] + [blaze.elm.compiler.core-spec] [blaze.elm.compiler.queries :as queries] - [blaze.elm.compiler.test-util :as tu] + [blaze.elm.compiler.test-util :as tu :refer [has-form]] [blaze.elm.literal] [blaze.elm.literal-spec] [blaze.elm.quantity :as quantity] @@ -62,9 +63,9 @@ [{:alias "S" :expression #elm/list - [#elm/quantity [2 "m"] - #elm/quantity [1 "m"] - #elm/quantity [1 "m"]]}] + [#elm/quantity [2 "m"] + #elm/quantity [1 "m"] + #elm/quantity [1 "m"]]}] :sort {:by [{:type "ByExpression" @@ -83,12 +84,12 @@ [{:alias "S" :expression #elm/list - [#elm/instance ["{urn:hl7-org:elm-types:r1}Code" - {"system" #elm/string "foo" - "code" #elm/string "c"}] - #elm/instance ["{urn:hl7-org:elm-types:r1}Code" - {"system" #elm/string "bar" - "code" #elm/string "c"}]]}] + [#elm/instance ["{urn:hl7-org:elm-types:r1}Code" + {"system" #elm/string "foo" + "code" #elm/string "c"}] + #elm/instance ["{urn:hl7-org:elm-types:r1}Code" + {"system" #elm/string "bar" + "code" #elm/string "c"}]]}] :sort {:by [{:type "ByExpression" @@ -111,8 +112,7 @@ (is (= [1 1] (core/-eval expr {} nil nil)))) (testing "form" - (is (= '(vector-query (return S (alias-ref S)) [1 1]) - (core/-form expr)))))) + (has-form expr '(vector-query (return (fn [S] (alias-ref S))) [1 1]))))) (testing "with query hint optimize first" (let [elm {:type "Query" @@ -125,73 +125,117 @@ (is (= [1] (into [] (core/-eval expr {} nil nil))))) (testing "form" - (is (= '(eduction-query distinct [1 1]) (core/-form expr))))))) + (has-form expr '(eduction-query distinct [1 1])))))) (testing "Retrieve queries" (with-system-data [{:blaze.db/keys [node]} mem-node-config] - [[[:put {:fhir/type :fhir/Patient :id "0"}]]] + [[[:put {:fhir/type :fhir/Patient :id "0" + :gender #fhir/code"female"}] + [:put {:fhir/type :fhir/Patient :id "1" + :gender #fhir/code"male"}]]] (let [db (d/db node) retrieve {:type "Retrieve" :dataType "{http://hl7.org/fhir}Patient"} where {:type "Equal" :operand - [{:path "gender" - :scope "P" - :type "Property" - :resultTypeName "{http://hl7.org/fhir}string" - :life/source-type "{http://hl7.org/fhir}Patient"} - #elm/integer "2"]} + [{:type "FunctionRef" + :name "ToString" + :operand + [{:path "gender" + :scope "P" + :type "Property" + :resultTypeName "{http://hl7.org/fhir}string"}]} + #elm/string "female"]} return {:path "gender" :scope "P" :type "Property" - :resultTypeName "{http://hl7.org/fhir}string" - :life/source-type "{http://hl7.org/fhir}Patient"}] - - (let [elm {:type "Query" - :source - [{:alias "P" - :expression retrieve}]} - expr (c/compile {:node node :eval-context "Unfiltered"} elm)] - - (testing "eval" - (given (core/-eval expr {:db db} nil nil) - [0 fhir-spec/fhir-type] := :fhir/Patient - [0 :id] := "0")) - - (testing "form" - (is (= '(vector-query distinct (retrieve "Patient")) (core/-form expr))))) - - (let [elm {:type "Query" - :source - [{:alias "P" - :expression retrieve}] - :where where} - expr (c/compile {:node node :eval-context "Unfiltered"} elm)] - (testing "eval" - (is (empty? (core/-eval expr {:db db} nil nil)))) - - (testing "form" - (is (= '(vector-query - (comp (where P (equal (:gender P) 2)) distinct) - (retrieve "Patient")) - (core/-form expr))))) - - (let [elm {:type "Query" - :source - [{:alias "P" - :expression retrieve}] - :return {:expression return}} - expr (c/compile {:node node :eval-context "Unfiltered"} elm)] - (is (nil? (first (core/-eval expr {:db db} nil nil))))) - - (let [elm {:type "Query" - :source - [{:alias "P" - :expression retrieve}] - :where where - :return {:expression return}} - expr (c/compile {:node node :eval-context "Unfiltered"} elm)] - (is (empty? (core/-eval expr {:db db} nil nil))))))) + :resultTypeName "{http://hl7.org/fhir}string"}] + + (testing "source only" + (let [elm {:type "Query" + :source + [{:alias "P" + :expression retrieve}]} + expr (c/compile {:node node :eval-context "Unfiltered"} elm)] + + (testing "eval" + (given (core/-eval expr {:db db} nil nil) + count := 2 + [0 fhir-spec/fhir-type] := :fhir/Patient + [0 :id] := "0" + [1 fhir-spec/fhir-type] := :fhir/Patient + [1 :id] := "1")) + + (testing "form" + (has-form expr '(vector-query distinct (retrieve "Patient")))))) + + (testing "with where clause" + (let [elm {:type "Query" + :source + [{:alias "P" + :expression retrieve}] + :where where} + expr (c/compile {:node node :eval-context "Unfiltered"} elm)] + + (testing "eval" + (given (core/-eval expr {:db db} nil nil) + count := 1 + [0 fhir-spec/fhir-type] := :fhir/Patient + [0 :id] := "0")) + + (testing "form" + (has-form expr + '(vector-query + (comp + (where + (fn [P] + (equal (call "ToString" (:gender P)) "female"))) + distinct) + (retrieve "Patient")))))) + + (testing "with return clause" + (let [elm {:type "Query" + :source + [{:alias "P" + :expression retrieve}] + :return {:expression return}} + expr (c/compile {:node node :eval-context "Unfiltered"} elm)] + + (testing "eval" + (given (core/-eval expr {:db db} nil nil) + count := 2 + [0] := #fhir/code"female" + [1] := #fhir/code"male")) + + (testing "form" + (has-form expr + '(vector-query + (distinct (return (fn [P] (:gender P)))) + (retrieve "Patient")))))) + + (testing "with where and return clauses" + (let [elm {:type "Query" + :source + [{:alias "P" + :expression retrieve}] + :where where + :return {:expression return}} + expr (c/compile {:node node :eval-context "Unfiltered"} elm)] + + (testing "eval" + (given (core/-eval expr {:db db} nil nil) + count := 1 + [0] := #fhir/code"female")) + + (testing "form" + (has-form expr + '(vector-query + (comp + (where + (fn [P] + (equal (call "ToString" (:gender P)) "female"))) + (distinct (return (fn [P] (:gender P))))) + (retrieve "Patient"))))))))) (testing "Unsupported With clause" (let [elm {:type "Query" @@ -242,7 +286,7 @@ (is (= ::result (core/-eval expr {} nil {"foo" ::result})))) (testing "form" - (is (= '(alias-ref foo) (core/-form expr)))))) + (has-form expr '(alias-ref foo))))) ;; 10.7. IdentifierRef @@ -256,7 +300,7 @@ (let [expr (c/compile {} {:type "IdentifierRef" :name "foo"})] (testing "form" - (is (= '(:foo default) (core/-form expr)))))) + (has-form expr '(:foo default))))) ;; TODO 10.9. QueryLetRef @@ -288,14 +332,12 @@ :scope "O0" :type "Property" :resultTypeName "{http://hl7.org/fhir}Reference" - :life/scopes #{"O0"} - :life/source-type "{http://hl7.org/fhir}Observation"} + :life/scopes #{"O0"}} {:path "subject" :scope "O1" :type "Property" :resultTypeName "{http://hl7.org/fhir}Reference" - :life/scopes #{"O1"} - :life/source-type "{http://hl7.org/fhir}Observation"}]} + :life/scopes #{"O1"}}]} compile-context {:node node :eval-context "Unfiltered"} xform-factory (queries/compile-with-equiv-clause compile-context "O0" elm) @@ -329,8 +371,7 @@ :scope "O" :type "Property" :resultTypeName "{http://hl7.org/fhir}Reference" - :life/scopes #{"O"} - :life/source-type "{http://hl7.org/fhir}Observation"}]} + :life/scopes #{"O"}}]} compile-context {:node node :eval-context "Unfiltered"} xform-factory (queries/compile-with-equiv-clause compile-context "P" elm) diff --git a/modules/cql/test/blaze/elm/compiler/reusing_logic_test.clj b/modules/cql/test/blaze/elm/compiler/reusing_logic_test.clj index 9c4dfe195..d95984342 100644 --- a/modules/cql/test/blaze/elm/compiler/reusing_logic_test.clj +++ b/modules/cql/test/blaze/elm/compiler/reusing_logic_test.clj @@ -5,10 +5,12 @@ https://cql.hl7.org/04-logicalspecification.html." (:require [blaze.anomaly :as ba] + [blaze.elm.code :as code] [blaze.elm.compiler :as c] [blaze.elm.compiler.core :as core] + [blaze.elm.compiler.core-spec] [blaze.elm.compiler.function :as function] - [blaze.elm.compiler.test-util :as tu] + [blaze.elm.compiler.test-util :as tu :refer [has-form]] [blaze.elm.interval :as interval] [blaze.elm.literal :as elm] [blaze.elm.literal-spec] @@ -59,11 +61,14 @@ expr (c/compile {:library library} #elm/expression-ref "name-170312")] (is (= ::result (core/-eval expr {:expression-defs {"name-170312" {:expression ::result}}} nil nil))))) - (testing "form" + (testing "form and static" (let [library {:statements {:def [{:type "ExpressionDef" :name "name-170312"}]}} expr (c/compile {:library library} #elm/expression-ref "name-170312")] - (is (= '(expr-ref "name-170312") (core/-form expr)))))) + + (has-form expr '(expr-ref "name-170312")) + + (is (false? (core/-static expr)))))) ;; 9.4. FunctionRef @@ -83,11 +88,15 @@ compile-ctx {:function-defs {function-name {:function (partial function/arity-n function-name fn-expr [])}}} elm (elm/function-ref [function-name]) expr (c/compile compile-ctx elm)] + (testing "eval" (is (= 1 (core/-eval expr {} nil nil)))) + (testing "static" + (is (false? (core/-static expr)))) + (testing "form" - (is (= `(~'call ~function-name) (core/-form expr)))))) + (has-form expr (list 'call function-name))))) (testing "Custom function with arity 1" (let [function-name "name-180815" @@ -96,14 +105,18 @@ :function-defs {function-name {:function (partial function/arity-n function-name fn-expr ["x"])}}} elm (elm/function-ref [function-name #elm/parameter-ref "a"]) expr (c/compile compile-ctx elm)] + (testing "eval" (are [a res] (= res (core/-eval expr {:parameters {"a" a}} nil nil)) 1 -1 -1 1 0 0)) + (testing "static" + (is (false? (core/-static expr)))) + (testing "form" - (is (= `(~'call ~function-name (~'param-ref "a")) (core/-form expr)))))) + (has-form expr (list 'call function-name '(param-ref "a")))))) (testing "Custom function with arity 2" (let [function-name "name-184652" @@ -112,33 +125,42 @@ :function-defs {function-name {:function (partial function/arity-n function-name fn-expr ["x" "y"])}}} elm (elm/function-ref [function-name #elm/parameter-ref "a" #elm/parameter-ref "b"]) expr (c/compile compile-ctx elm)] + (testing "eval" (are [a b res] (= res (core/-eval expr {:parameters {"a" a "b" b}} nil nil)) 1 1 2 1 0 1 0 1 1)) + (testing "static" + (is (false? (core/-static expr)))) + (testing "form" - (is (= `(~'call ~function-name (~'param-ref "a") (~'param-ref "b")) (core/-form expr)))))) + (has-form expr (list 'call function-name '(param-ref "a") '(param-ref "b")))))) (testing "ToQuantity" (let [compile-ctx {:library {:parameters {:def [{:name "x"}]}}} elm #elm/function-ref ["ToQuantity" #elm/parameter-ref "x"] expr (c/compile compile-ctx elm)] + (testing "eval" (are [x res] (= res (core/-eval expr {:parameters {"x" x}} nil nil)) {:value 23M :code "kg"} (quantity/quantity 23M "kg") {:value 42M} (quantity/quantity 42M "1") {} nil)) + (testing "static" + (is (false? (core/-static expr)))) + (testing "form" - (is (= '(call "ToQuantity" (param-ref "x")) (core/-form expr)))))) + (has-form expr '(call "ToQuantity" (param-ref "x")))))) (testing "ToDate" (let [compile-ctx {:library {:parameters {:def [{:name "x"}]}}} elm #elm/function-ref ["ToDate" #elm/parameter-ref "x"] expr (c/compile compile-ctx elm) - eval-ctx (fn [x] {:now tu/now :parameters {"x" x}})] + eval-ctx (fn [x] {:now tu/now :parameters {"x" x}}) + ] (testing "eval" (are [x res] (= res (core/-eval expr (eval-ctx x) nil nil)) #fhir/date{:id "foo"} nil @@ -147,14 +169,18 @@ #fhir/date"2023-05" #system/date"2023-05" #fhir/date"2023-05-07" #system/date"2023-05-07")) + (testing "static" + (is (false? (core/-static expr)))) + (testing "form" - (is (= '(call "ToDate" (param-ref "x")) (core/-form expr)))))) + (has-form expr '(call "ToDate" (param-ref "x")))))) (testing "ToDateTime" (let [compile-ctx {:library {:parameters {:def [{:name "x"}]}}} elm #elm/function-ref ["ToDateTime" #elm/parameter-ref "x"] expr (c/compile compile-ctx elm) eval-ctx (fn [x] {:now tu/now :parameters {"x" x}})] + (testing "eval" (are [x res] (= res (core/-eval expr (eval-ctx x) nil nil)) #fhir/dateTime{:id "foo"} nil @@ -169,13 +195,17 @@ #fhir/instant"2021-02-23T15:12:45Z" #system/date-time"2021-02-23T15:12:45" #fhir/instant"2021-02-23T15:12:45+01:00" #system/date-time"2021-02-23T14:12:45")) + (testing "static" + (is (false? (core/-static expr)))) + (testing "form" - (is (= '(call "ToDateTime" (param-ref "x")) (core/-form expr)))))) + (has-form expr '(call "ToDateTime" (param-ref "x")))))) (testing "ToString" (let [compile-ctx {:library {:parameters {:def [{:name "x"}]}}} elm #elm/function-ref ["ToString" #elm/parameter-ref "x"] expr (c/compile compile-ctx elm)] + (testing "eval" (are [x res] (= res (core/-eval expr {:parameters {"x" x}} nil nil)) "string-195733" "string-195733" @@ -183,14 +213,36 @@ #fhir/code{:id "foo" :value "code-211914"} "code-211914" #fhir/code{:id "foo"} nil)) + (testing "static" + (is (false? (core/-static expr)))) + (testing "form" - (is (= '(call "ToString" (param-ref "x")) (core/-form expr)))))) + (has-form expr '(call "ToString" (param-ref "x")))))) + + (testing "ToCode" + (let [compile-ctx {:library {:parameters {:def [{:name "x"}]}}} + elm #elm/function-ref ["ToCode" #elm/parameter-ref "x"] + expr (c/compile compile-ctx elm)] + + (testing "eval" + (are [x res] (= res (core/-eval expr {:parameters {"x" x}} nil nil)) + {:system "system-140820" + :version "version-140924" + :code "code-140828"} + (code/to-code "system-140820" "version-140924" "code-140828"))) + + (testing "static" + (is (false? (core/-static expr)))) + + (testing "form" + (has-form expr '(call "ToCode" (param-ref "x")))))) (testing "ToInterval" (let [compile-ctx {:library {:parameters {:def [{:name "x"}]}}} elm #elm/function-ref ["ToInterval" #elm/parameter-ref "x"] expr (c/compile compile-ctx elm) eval-ctx (fn [x] {:now tu/now :parameters {"x" x}})] + (testing "eval" (are [x res] (= res (core/-eval expr (eval-ctx x) nil nil)) #fhir/Period @@ -212,8 +264,11 @@ (system/date-time 2021 2 23 14 12 45) nil))) + (testing "static" + (is (false? (core/-static expr)))) + (testing "form" - (is (= '(call "ToInterval" (param-ref "x")) (core/-form expr))))))) + (has-form expr '(call "ToInterval" (param-ref "x"))))))) ;; 9.5 OperandRef @@ -221,5 +276,7 @@ ;; The OperandRef expression allows the value of an operand to be referenced as ;; part of an expression within the body of a function definition. (deftest compile-operand-ref-test - (testing "form" - (is (= '(operand-ref "x") (core/-form (c/compile {} #elm/operand-ref"x")))))) + (testing "form and static" + (let [expr (c/compile {} #elm/operand-ref"x")] + (has-form expr '(operand-ref "x")) + (is (false? (core/-static expr)))))) diff --git a/modules/cql/test/blaze/elm/compiler/simple_values_test.clj b/modules/cql/test/blaze/elm/compiler/simple_values_test.clj index 59c3feac8..440f4bdca 100644 --- a/modules/cql/test/blaze/elm/compiler/simple_values_test.clj +++ b/modules/cql/test/blaze/elm/compiler/simple_values_test.clj @@ -36,12 +36,12 @@ ;; the boolean value true or the string "antithrombotic". (deftest compile-literal-test (testing "Boolean Literal" - (are [elm res] (= res (c/compile {} elm)) + (are [elm res] (let [expr (c/compile {} elm)] (= res expr (c/form expr))) #elm/boolean "true" true #elm/boolean "false" false)) (testing "Decimal Literal" - (are [elm res] (= res (c/compile {} elm)) + (are [elm res] (let [expr (c/compile {} elm)] (= res expr (c/form expr))) #elm/decimal "-1" -1M #elm/decimal "0" 0M #elm/decimal "1" 1M @@ -62,7 +62,7 @@ ::anom/message := "Incorrect decimal literal `x`."))) (testing "Long Literal" - (are [elm res] (= res (c/compile {} elm)) + (are [elm res] (let [expr (c/compile {} elm)] (= res expr (c/form expr))) #elm/long "-1" -1 #elm/long "0" 0 #elm/long "1" 1) @@ -73,7 +73,7 @@ ::anom/message := "Incorrect long literal `x`."))) (testing "Integer Literal" - (are [elm res] (= res (c/compile {} elm)) + (are [elm res] (let [expr (c/compile {} elm)] (= res expr (c/form expr))) #elm/integer "-1" -1 #elm/integer "0" 0 #elm/integer "1" 1) diff --git a/modules/cql/test/blaze/elm/compiler/string_operators_test.clj b/modules/cql/test/blaze/elm/compiler/string_operators_test.clj index 5bc9923d8..f8c8df716 100644 --- a/modules/cql/test/blaze/elm/compiler/string_operators_test.clj +++ b/modules/cql/test/blaze/elm/compiler/string_operators_test.clj @@ -8,11 +8,12 @@ [blaze.db.api-stub :refer [mem-node-config with-system-data]] [blaze.elm.compiler :as c] [blaze.elm.compiler.core :as core] - [blaze.elm.compiler.test-util :as tu] + [blaze.elm.compiler.core-spec] + [blaze.elm.compiler.test-util :as tu :refer [has-form]] [blaze.elm.literal :as elm] [blaze.elm.literal-spec] [clojure.spec.test.alpha :as st] - [clojure.test :as test :refer [are deftest testing]])) + [clojure.test :as test :refer [are deftest is testing]])) (st/instrument) @@ -47,7 +48,15 @@ #elm/list [] nil #elm/list [#elm/string "a" {:type "Null"}] nil #elm/list [{:type "Null"}] nil - {:type "Null"} nil)) + {:type "Null"} nil) + + (testing "form and static" + (let [expr (tu/dynamic-compile {:type "Combine" + :source #elm/parameter-ref "x"})] + + (has-form expr '(combine (param-ref "x"))) + + (is (false? (core/-static expr)))))) (testing "With separator" (are [src res] (= res (core/-eval (c/compile {} {:type "Combine" :source src :separator #elm/string " "}) {} nil nil)) @@ -57,7 +66,16 @@ #elm/list [] nil #elm/list [#elm/string "a" {:type "Null"}] nil #elm/list [{:type "Null"}] nil - {:type "Null"} nil))) + {:type "Null"} nil) + + (testing "form and static" + (let [expr (tu/dynamic-compile {:type "Combine" + :source #elm/parameter-ref "x" + :separator #elm/parameter-ref "y"})] + + (has-form expr '(combine (param-ref "x") (param-ref "y"))) + + (is (false? (core/-static expr))))))) ;; 17.2. Concatenate @@ -74,10 +92,16 @@ [{:type "Null"}] nil) (testing "form" - (are [args form] (= form (core/-form (c/compile {} {:type "Concatenate" :operand args}))) + (are [args form] (= form (c/form (c/compile {} {:type "Concatenate" :operand args}))) [#elm/string "a"] '(concatenate "a") [#elm/string "a" #elm/string "b"] '(concatenate "a" "b") - [#elm/string "a" {:type "Null"}] '(concatenate "a" nil)))) + [#elm/string "a" {:type "Null"}] '(concatenate "a" nil))) + + (testing "static" + (are [args] (false? (core/-static (c/compile {} {:type "Concatenate" :operand args}))) + [#elm/string "a"] + [#elm/string "a" #elm/string "b"] + [#elm/string "a" {:type "Null"}]))) ;; 17.3. EndsWith @@ -97,7 +121,7 @@ #elm/string "a" #elm/string "b" false #elm/string "ba" #elm/string "b" false)) - (testing "dynamic" + (testing "Dynamic" (are [s suffix res] (= res (tu/dynamic-compile-eval (elm/ends-with [s suffix]))) #elm/parameter-ref "a" #elm/string "a" true #elm/parameter-ref "ab" #elm/string "b" true @@ -107,6 +131,8 @@ (tu/testing-binary-null elm/ends-with #elm/string "a") + (tu/testing-binary-dynamic elm/ends-with) + (tu/testing-binary-form elm/ends-with)) @@ -151,6 +177,8 @@ (tu/testing-binary-null elm/indexer #elm/list [] #elm/integer "0")) + (tu/testing-binary-dynamic elm/indexer) + (tu/testing-binary-form elm/indexer)) @@ -163,15 +191,17 @@ ;; ;; If either argument is null, the result is null. (deftest compile-last-position-of-test - (are [pattern s res] (= res (core/-eval (c/compile {} {:type "LastPositionOf" :pattern pattern :string s}) {} nil nil)) + (are [pattern s res] (= res (core/-eval (c/compile {} (elm/last-position-of [pattern s])) {} nil nil)) #elm/string "a" #elm/string "a" 0 #elm/string "a" #elm/string "aa" 1 - #elm/string "a" #elm/string "b" -1 + #elm/string "a" #elm/string "b" -1) + + (tu/testing-binary-dynamic-null elm/last-position-of #elm/string "a" #elm/string "a") - {:type "Null"} #elm/string "a" nil - #elm/string "a" {:type "Null"} nil - {:type "Null"} {:type "Null"} nil)) + (tu/testing-binary-dynamic elm/last-position-of) + + (tu/testing-binary-form elm/last-position-of)) ;; 17.8. Length @@ -195,7 +225,7 @@ {:type "Null"} 0)) - (testing "dynamic" + (testing "Dynamic" (are [x res] (identical? res (tu/dynamic-compile-eval (elm/length x))) #elm/parameter-ref "empty-string" 0 #elm/parameter-ref "a" 1 @@ -221,6 +251,8 @@ (identical? count (core/-eval expr {:db db} patient nil)))) 0 1 2)) + (tu/testing-unary-dynamic elm/length) + (tu/testing-unary-form elm/length)) @@ -241,13 +273,15 @@ #elm/string "" "" #elm/string "A" "a")) - (testing "dynamic" + (testing "Dynamic" (are [s res] (= res (tu/dynamic-compile-eval (elm/lower s))) #elm/parameter-ref "empty-string" "" #elm/parameter-ref "A" "a")) (tu/testing-unary-null elm/lower) + (tu/testing-unary-dynamic elm/lower) + (tu/testing-unary-form elm/lower)) @@ -272,6 +306,8 @@ (tu/testing-binary-null elm/matches #elm/string "a") + (tu/testing-binary-dynamic elm/matches) + (tu/testing-binary-form elm/matches)) @@ -289,15 +325,17 @@ ;; ;; If either argument is null, the result is null. (deftest compile-position-of-test - (are [pattern s res] (= res (core/-eval (c/compile {} {:type "PositionOf" :pattern pattern :string s}) {} nil nil)) + (are [pattern s res] (= res (core/-eval (c/compile {} (elm/position-of [pattern s])) {} nil nil)) #elm/string "a" #elm/string "a" 0 #elm/string "a" #elm/string "aa" 0 - #elm/string "a" #elm/string "b" -1 + #elm/string "a" #elm/string "b" -1) + + (tu/testing-binary-dynamic-null elm/position-of #elm/string "a" #elm/string "a") + + (tu/testing-binary-dynamic elm/position-of) - {:type "Null"} #elm/string "a" nil - #elm/string "a" {:type "Null"} nil - {:type "Null"} {:type "Null"} nil)) + (tu/testing-binary-form elm/position-of)) ;; 17.13. ReplaceMatches @@ -316,12 +354,14 @@ ;; such, CQL does not prescribe a particular dialect, but recommends the use of ;; the PCRE dialect. (deftest compile-replace-matches-test - (are [s pattern substitution res] (= res (core/-eval (c/compile {} {:type "ReplaceMatches" :operand [s pattern substitution]}) {} nil nil)) - #elm/string "a" #elm/string "a" #elm/string "b" "b" + (are [s pattern substitution res] (= res (core/-eval (c/compile {} (elm/replace-matches [s pattern substitution])) {} nil nil)) + #elm/string "a" #elm/string "a" #elm/string "b" "b") - {:type "Null"} #elm/string "a" {:type "Null"} nil - #elm/string "a" {:type "Null"} {:type "Null"} nil - {:type "Null"} {:type "Null"} {:type "Null"} nil)) + (tu/testing-ternary-dynamic-null elm/replace-matches #elm/string "a" #elm/string "a" #elm/string "a") + + (tu/testing-ternary-dynamic elm/replace-matches) + + (tu/testing-ternary-form elm/replace-matches)) ;; 17.14. Split @@ -339,7 +379,15 @@ #elm/string "" [""] #elm/string "a" ["a"] - {:type "Null"} nil)) + {:type "Null"} nil) + + (testing "form and static" + (let [expr (tu/dynamic-compile {:type "Split" + :stringToSplit #elm/parameter-ref "x"})] + + (has-form expr '(split (param-ref "x"))) + + (is (false? (core/-static expr)))))) (testing "With separator" (are [s separator res] (= res (core/-eval (c/compile {} {:type "Split" :stringToSplit s :separator separator}) {} nil nil)) @@ -349,7 +397,16 @@ {:type "Null"} #elm/string "," nil #elm/string "a" {:type "Null"} ["a"] - {:type "Null"} {:type "Null"} nil))) + {:type "Null"} {:type "Null"} nil) + + (testing "form and static" + (let [expr (tu/dynamic-compile {:type "Split" + :stringToSplit #elm/parameter-ref "x" + :separator #elm/parameter-ref "y"})] + + (has-form expr '(split (param-ref "x") (param-ref "y"))) + + (is (false? (core/-static expr))))))) ;; 17.15. SplitOnMatches @@ -384,7 +441,7 @@ #elm/string "a" #elm/string "b" false #elm/string "ab" #elm/string "b" false)) - (testing "dynamic" + (testing "Dynamic" (are [s prefix res] (= res (tu/dynamic-compile-eval (elm/starts-with [s prefix]))) #elm/parameter-ref "a" #elm/string "a" true #elm/parameter-ref "ba" #elm/string "b" true @@ -394,6 +451,8 @@ (tu/testing-binary-null elm/starts-with #elm/string "a") + (tu/testing-binary-dynamic elm/starts-with) + (tu/testing-binary-form elm/starts-with)) @@ -418,7 +477,16 @@ #elm/string "a" #elm/integer "1" nil {:type "Null"} #elm/integer "0" nil #elm/string "a" {:type "Null"} nil - {:type "Null"} {:type "Null"} nil)) + {:type "Null"} {:type "Null"} nil) + + (testing "form and static" + (let [expr (tu/dynamic-compile {:type "Substring" + :stringToSub #elm/parameter-ref "x" + :startIndex #elm/parameter-ref "y"})] + + (has-form expr '(substring (param-ref "x") (param-ref "y"))) + + (is (false? (core/-static expr)))))) (testing "With length" (are [s start-index length res] (= res (core/-eval (c/compile {} {:type "Substring" :stringToSub s :startIndex start-index :length length}) {} nil nil)) @@ -430,7 +498,17 @@ #elm/string "a" #elm/integer "2" #elm/integer "0" nil {:type "Null"} #elm/integer "0" #elm/integer "0" nil #elm/string "a" {:type "Null"} #elm/integer "0" nil - {:type "Null"} {:type "Null"} #elm/integer "0" nil))) + {:type "Null"} {:type "Null"} #elm/integer "0" nil) + + (testing "form and static" + (let [expr (tu/dynamic-compile {:type "Substring" + :stringToSub #elm/parameter-ref "x" + :startIndex #elm/parameter-ref "y" + :length #elm/parameter-ref "z"})] + + (has-form expr '(substring (param-ref "x") (param-ref "y") (param-ref "z"))) + + (is (false? (core/-static expr))))))) ;; 17.18. Upper @@ -450,11 +528,13 @@ #elm/string "" "" #elm/string "a" "A")) - (testing "dynamic" + (testing "Dynamic" (are [s res] (= res (tu/dynamic-compile-eval (elm/upper s))) #elm/parameter-ref "empty-string" "" #elm/parameter-ref "a" "A")) (tu/testing-unary-null elm/upper) + (tu/testing-unary-dynamic elm/upper) + (tu/testing-unary-form elm/upper)) diff --git a/modules/cql/test/blaze/elm/compiler/structured_values_test.clj b/modules/cql/test/blaze/elm/compiler/structured_values_test.clj index ec2fc00e2..558e2e056 100644 --- a/modules/cql/test/blaze/elm/compiler/structured_values_test.clj +++ b/modules/cql/test/blaze/elm/compiler/structured_values_test.clj @@ -8,7 +8,8 @@ [blaze.elm.code-spec] [blaze.elm.compiler :as c] [blaze.elm.compiler.core :as core] - [blaze.elm.compiler.test-util :as tu] + [blaze.elm.compiler.core-spec] + [blaze.elm.compiler.test-util :as tu :refer [has-form]] [blaze.elm.literal] [blaze.elm.literal-spec] [blaze.fhir.spec.type] @@ -41,12 +42,28 @@ ;; elements of the tuple. Note that the value of an element may be any ;; expression, including another Tuple. (deftest compile-tuple-test - (are [elm res] (= res (core/-eval (c/compile {} elm) {} nil nil)) - #elm/tuple{"id" #elm/integer "1"} - {:id 1} + (testing "Static" + (are [elm res] (= res (core/-eval (c/compile {} elm) {} nil nil)) + #elm/tuple{"id" #elm/integer "1"} + {:id 1} - #elm/tuple{"id" #elm/integer "1" "name" #elm/string "john"} - {:id 1 :name "john"})) + #elm/tuple{"id" #elm/integer "1" "name" #elm/string "john"} + {:id 1 :name "john"})) + + (testing "Dynamic" + (are [elm res] (= res (tu/dynamic-compile-eval elm)) + #elm/tuple{"id" #elm/parameter-ref "1"} + {:id 1} + + #elm/tuple{"id" #elm/parameter-ref "1" "name" #elm/parameter-ref "a"} + {:id 1 :name "a"}) + + (testing "static" + (is (false? (core/-static (tu/dynamic-compile #elm/tuple{"id" #elm/parameter-ref "1"}))))) + + (testing "form" + (is (= '{:id (param-ref "x")} + (core/-form (tu/dynamic-compile #elm/tuple{"id" #elm/parameter-ref "x"}))))))) ;; 2.2. Instance @@ -94,24 +111,27 @@ (let [elm {:path "identifier" :scope "R" - :type "Property" - :life/source-type "{http://hl7.org/fhir}Patient"} + :type "Property"} identifier #fhir/Identifier - {:system #fhir/uri"foo" - :value "bar"} + {:system #fhir/uri"foo" + :value "bar"} entity {:fhir/type :fhir/Patient :id "0" :identifier [identifier]} expr (c/compile {:eval-context "Patient"} - elm) - result (coll/first (core/-eval expr nil nil {"R" entity}))] - (is (= identifier result)) + elm)] + + (testing "eval" + (is (= identifier (coll/first (core/-eval expr nil nil {"R" entity}))))) + + (testing "expression is dynamic" + (is (false? (core/-static expr)))) (testing "form" - (is (= '(:identifier R) (core/-form expr)))))) + (has-form expr '(:identifier R))))) (testing "without source-type" (let [elm @@ -120,17 +140,24 @@ :type "Property"} identifier #fhir/Identifier - {:system #fhir/uri"foo" - :value "bar"} + {:system #fhir/uri"foo" + :value "bar"} entity {:fhir/type :fhir/Patient :id "0" :identifier [identifier]} expr (c/compile {:eval-context "Patient"} - elm) - result (coll/first (core/-eval expr nil nil {"R" entity}))] - (is (= identifier result))))) + elm)] + + (testing "eval" + (is (= identifier (coll/first (core/-eval expr nil nil {"R" entity}))))) + + (testing "expression is dynamic" + (is (false? (core/-static expr)))) + + (testing "form" + (has-form expr '(:identifier R)))))) (testing "Patient.extension" (testing "without source-type" @@ -140,25 +167,31 @@ :type "Property"} extension #fhir/Extension - {:url "foo" - :valueString "bar"} + {:url "foo" + :valueString "bar"} entity {:fhir/type :fhir/Patient :id "0" :extension [extension]} expr (c/compile {:eval-context "Patient"} - elm) - result (coll/first (core/-eval expr nil nil {"R" entity}))] - (is (= extension result))))) + elm)] + + (testing "eval" + (is (= extension (coll/first (core/-eval expr nil nil {"R" entity}))))) + + (testing "expression is dynamic" + (is (false? (core/-static expr)))) + + (testing "form" + (has-form expr '(:extension R)))))) (testing "Patient.gender" (testing "with source-type" (let [elm {:path "gender" :scope "R" - :type "Property" - :life/source-type "{http://hl7.org/fhir}Patient"} + :type "Property"} entity {:fhir/type :fhir/Patient :id "0" :gender #fhir/code"male"} @@ -166,7 +199,15 @@ (c/compile {:eval-context "Patient"} elm)] - (is (= #fhir/code"male" (core/-eval expr nil nil {"R" entity}))))) + + (testing "eval" + (is (= #fhir/code"male" (core/-eval expr nil nil {"R" entity})))) + + (testing "expression is dynamic" + (is (false? (core/-static expr)))) + + (testing "form" + (has-form expr '(:gender R))))) (testing "without source-type" (let [elm @@ -180,7 +221,15 @@ (c/compile {:eval-context "Patient"} elm)] - (is (= #fhir/code"male" (core/-eval expr nil nil {"R" entity})))))) + + (testing "eval" + (is (= #fhir/code"male" (core/-eval expr nil nil {"R" entity})))) + + (testing "expression is dynamic" + (is (false? (core/-static expr)))) + + (testing "form" + (has-form expr '(:gender R)))))) (testing "Patient.birthDate.value" (let [elm @@ -195,19 +244,26 @@ (c/compile {:eval-context "Patient"} elm)] - (are [birth-date res] (= res (core/-eval expr nil nil {"R" (entity birth-date)})) - #fhir/date"2023-05-07" #system/date"2023-05-07" - #fhir/date{:id "foo" :value "2023-05-07"} #system/date"2023-05-07" - #fhir/date{:id "foo"} nil - #fhir/date{:extension [#fhir/Extension{:url "foo"}]} nil))) + + (testing "eval" + (are [birth-date res] (= res (core/-eval expr nil nil {"R" (entity birth-date)})) + #fhir/date"2023-05-07" #system/date"2023-05-07" + #fhir/date{:id "foo" :value "2023-05-07"} #system/date"2023-05-07" + #fhir/date{:id "foo"} nil + #fhir/date{:extension [#fhir/Extension{:url "foo"}]} nil)) + + (testing "expression is dynamic" + (is (false? (core/-static expr)))) + + (testing "form" + (has-form expr '(:value (:birthDate R)))))) (testing "Observation.value" (testing "with source-type" (let [elm {:path "value" :scope "R" - :type "Property" - :life/source-type "{http://hl7.org/fhir}Observation"} + :type "Property"} entity {:fhir/type :fhir/Observation :id "0" :value "value-114318"} @@ -215,7 +271,15 @@ (c/compile {:eval-context "Patient"} elm)] - (is (= "value-114318" (core/-eval expr nil nil {"R" entity}))))) + + (testing "eval" + (is (= "value-114318" (core/-eval expr nil nil {"R" entity})))) + + (testing "expression is dynamic" + (is (false? (core/-static expr)))) + + (testing "form" + (has-form expr '(:value R))))) (testing "without source-type" (let [elm @@ -229,7 +293,15 @@ (c/compile {:eval-context "Patient"} elm)] - (is (= "value-114318" (core/-eval expr nil nil {"R" entity})))))))) + + (testing "eval" + (is (= "value-114318" (core/-eval expr nil nil {"R" entity})))) + + (testing "expression is dynamic" + (is (false? (core/-static expr)))) + + (testing "form" + (has-form expr '(:value R)))))))) (testing "with source" (testing "Patient.identifier" @@ -239,21 +311,24 @@ elm {:path "identifier" :source #elm/expression-ref "Patient" - :type "Property" - :life/source-type "{http://hl7.org/fhir}Patient"} + :type "Property"} identifier #fhir/Identifier - {:system #fhir/uri"foo" - :value "bar"} + {:system #fhir/uri"foo" + :value "bar"} source {:fhir/type :fhir/Patient :id "0" :identifier [identifier]} - expr (c/compile {:library library :eval-context "Patient"} elm) - result (coll/first (core/-eval expr {:expression-defs {"Patient" {:expression source}}} nil nil))] - (is (= identifier result)) + expr (c/compile {:library library :eval-context "Patient"} elm)] + + (testing "eval" + (is (= identifier (coll/first (core/-eval expr {:expression-defs {"Patient" {:expression source}}} nil nil))))) + + (testing "expression is dynamic" + (is (false? (core/-static expr)))) (testing "form" - (is (= '(:identifier (expr-ref "Patient")) (core/-form expr)))))) + (has-form expr '(:identifier (expr-ref "Patient")))))) (testing "without source-type" (let [library {:statements {:def [{:type "ExpressionDef" @@ -264,14 +339,21 @@ :type "Property"} identifier #fhir/Identifier - {:system #fhir/uri"foo" - :value "bar"} + {:system #fhir/uri"foo" + :value "bar"} source {:fhir/type :fhir/Patient :id "0" :identifier [identifier]} - expr (c/compile {:library library :eval-context "Patient"} elm) - result (coll/first (core/-eval expr {:expression-defs {"Patient" {:expression source}}} nil nil))] - (is (= identifier result))))) + expr (c/compile {:library library :eval-context "Patient"} elm)] + + (testing "eval" + (is (= identifier (coll/first (core/-eval expr {:expression-defs {"Patient" {:expression source}}} nil nil))))) + + (testing "expression is dynamic" + (is (false? (core/-static expr)))) + + (testing "form" + (has-form expr '(:identifier (expr-ref "Patient"))))))) (testing "Patient.gender" (testing "with source-type" @@ -280,14 +362,20 @@ elm {:path "gender" :source #elm/expression-ref "Patient" - :type "Property" - :life/source-type "{http://hl7.org/fhir}Patient"} + :type "Property"} source {:fhir/type :fhir/Patient :id "0" :gender #fhir/code"male"} - expr (c/compile {:library library :eval-context "Patient"} elm) - result (core/-eval expr {:expression-defs {"Patient" {:expression source}}} nil nil)] - (is (= #fhir/code"male" result)))) + expr (c/compile {:library library :eval-context "Patient"} elm)] + + (testing "eval" + (is (= #fhir/code"male" (core/-eval expr {:expression-defs {"Patient" {:expression source}}} nil nil)))) + + (testing "expression is dynamic" + (is (false? (core/-static expr)))) + + (testing "form" + (has-form expr '(:gender (expr-ref "Patient")))))) (testing "without source-type" (let [library {:statements {:def [{:type "ExpressionDef" @@ -299,9 +387,16 @@ source {:fhir/type :fhir/Patient :id "0" :gender #fhir/code"male"} - expr (c/compile {:library library :eval-context "Patient"} elm) - result (core/-eval expr {:expression-defs {"Patient" {:expression source}}} nil nil)] - (is (= #fhir/code"male" result))))) + expr (c/compile {:library library :eval-context "Patient"} elm)] + + (testing "eval" + (is (= #fhir/code"male" (core/-eval expr {:expression-defs {"Patient" {:expression source}}} nil nil)))) + + (testing "expression is dynamic" + (is (false? (core/-static expr)))) + + (testing "form" + (has-form expr '(:gender (expr-ref "Patient"))))))) (testing "Patient.birthDate.value" (let [library {:statements {:def [{:type "ExpressionDef" @@ -315,11 +410,19 @@ {:fhir/type :fhir/Patient :id "0" :birthDate x}) expr (c/compile {:library library :eval-context "Patient"} elm)] - (are [birth-date res] (= res (core/-eval expr {:expression-defs {"Patient" {:expression (source birth-date)}}} nil nil)) - #fhir/date"2023-05-07" #system/date"2023-05-07" - #fhir/date{:id "foo" :value "2023-05-07"} #system/date"2023-05-07" - #fhir/date{:id "foo"} nil - #fhir/date{:extension [#fhir/Extension{:url "foo"}]} nil))) + + (testing "eval" + (are [birth-date res] (= res (core/-eval expr {:expression-defs {"Patient" {:expression (source birth-date)}}} nil nil)) + #fhir/date"2023-05-07" #system/date"2023-05-07" + #fhir/date{:id "foo" :value "2023-05-07"} #system/date"2023-05-07" + #fhir/date{:id "foo"} nil + #fhir/date{:extension [#fhir/Extension{:url "foo"}]} nil)) + + (testing "expression is dynamic" + (is (false? (core/-static expr)))) + + (testing "form" + (has-form expr '(:value (:birthDate (expr-ref "Patient"))))))) (testing "Observation.value" (testing "with source-type" @@ -328,14 +431,20 @@ elm {:path "value" :source #elm/expression-ref "Observation" - :type "Property" - :life/source-type "{http://hl7.org/fhir}Observation"} + :type "Property"} source {:fhir/type :fhir/Observation :id "0" :value "value-114318"} - expr (c/compile {:library library :eval-context "Patient"} elm) - result (core/-eval expr {:expression-defs {"Observation" {:expression source}}} nil nil)] - (is (= "value-114318" result)))) + expr (c/compile {:library library :eval-context "Patient"} elm)] + + (testing "eval" + (is (= "value-114318" (core/-eval expr {:expression-defs {"Observation" {:expression source}}} nil nil)))) + + (testing "expression is dynamic" + (is (false? (core/-static expr)))) + + (testing "form" + (has-form expr '(:value (expr-ref "Observation")))))) (testing "without source-type" (let [library {:statements {:def [{:type "ExpressionDef" @@ -347,9 +456,16 @@ source {:fhir/type :fhir/Observation :id "0" :value "value-114318"} - expr (c/compile {:library library :eval-context "Patient"} elm) - result (core/-eval expr {:expression-defs {"Observation" {:expression source}}} nil nil)] - (is (= "value-114318" result))))) + expr (c/compile {:library library :eval-context "Patient"} elm)] + + (testing "eval" + (is (= "value-114318" (core/-eval expr {:expression-defs {"Observation" {:expression source}}} nil nil)))) + + (testing "expression is dynamic" + (is (false? (core/-static expr)))) + + (testing "form" + (has-form expr '(:value (expr-ref "Observation"))))))) (testing "Tuple" (are [elm result] diff --git a/modules/cql/test/blaze/elm/compiler/test_util.clj b/modules/cql/test/blaze/elm/compiler/test_util.clj index df9e4121b..6e39cbc1f 100644 --- a/modules/cql/test/blaze/elm/compiler/test_util.clj +++ b/modules/cql/test/blaze/elm/compiler/test_util.clj @@ -2,6 +2,8 @@ (:require [blaze.elm.compiler :as c] [blaze.elm.compiler.core :as core] + [blaze.elm.compiler.core-spec] + [blaze.elm.expression :as-alias expr] [blaze.elm.literal :as elm] [blaze.elm.literal-spec] [blaze.elm.spec] @@ -52,31 +54,42 @@ [{:name "true"} {:name "false"} {:name "nil"} + {:name "-1"} {:name "1"} {:name "2"} {:name "3"} {:name "4"} {:name "empty-string"} + {:name "x"} + {:name "y"} + {:name "z"} {:name "a"} {:name "ab"} {:name "b"} {:name "ba"} {:name "A"} {:name "12:54:00"} - {:name "2020-01-02T03:04:05.006Z"}]}}}) + {:name "2020-01-02T03:04:05.006Z"} + {:name "[1]"} + {:name "[1 2]"}]}}}) (def dynamic-eval-ctx {:parameters - {"true" true "false" false "nil" nil "1" 1 "2" 2 "3" 3 "4" 4 - "empty-string" "" "a" "a" "ab" "ab" "b" "b" "ba" "ba" "A" "A" + {"true" true "false" false "nil" nil "-1" -1 "1" 1 "2" 2 "3" 3 "4" 4 + "empty-string" "" "x" "x" "y" "y" "z" "z" "a" "a" "ab" "ab" "b" "b" "ba" "ba" "A" "A" "12:54:00" (system/time 12 54 00) - "2020-01-02T03:04:05.006Z" (system/date-time 2020 1 2 3 4 5 6 ZoneOffset/UTC)} + "2020-01-02T03:04:05.006Z" (system/date-time 2020 1 2 3 4 5 6 ZoneOffset/UTC) + "[1]" [1] "[1 2]" [1 2]} :now now}) +(defn dynamic-compile [elm] + (c/compile dynamic-compile-ctx elm)) + + (defn dynamic-compile-eval [elm] - (core/-eval (c/compile dynamic-compile-ctx elm) dynamic-eval-ctx nil nil)) + (core/-eval (dynamic-compile elm) dynamic-eval-ctx nil nil)) (defn binary-operand [type] @@ -119,7 +132,8 @@ (is (nil? (c/compile {} (~elm-constructor [{:type "Null"} ~non-null-op-2])))))) -(defmacro testing-binary-dynamic-null [elm-constructor non-null-op-1 non-null-op-2] +(defmacro testing-binary-dynamic-null + [elm-constructor non-null-op-1 non-null-op-2] `(testing "Dynamic Null" (let [elm# (~elm-constructor [#elm/parameter-ref "nil" @@ -135,6 +149,26 @@ (is (nil? (dynamic-compile-eval elm#)))))) +(defmacro testing-ternary-dynamic-null + [elm-constructor non-null-op-1 non-null-op-2 non-null-op-3] + `(testing "Dynamic Null" + (let [elm# (~elm-constructor + [#elm/parameter-ref "nil" + ~non-null-op-2 + ~non-null-op-3])] + (is (nil? (dynamic-compile-eval elm#)))) + (let [elm# (~elm-constructor + [~non-null-op-1 + #elm/parameter-ref "nil" + ~non-null-op-3])] + (is (nil? (dynamic-compile-eval elm#)))) + (let [elm# (~elm-constructor + [~non-null-op-1 + ~non-null-op-2 + #elm/parameter-ref "nil"])] + (is (nil? (dynamic-compile-eval elm#)))))) + + (defmacro testing-binary-null ([elm-constructor non-null-op] `(testing-binary-null ~elm-constructor ~non-null-op ~non-null-op)) @@ -163,22 +197,25 @@ (c/compile {} (constructor [(op-constructor op-1) (op-constructor op-2) precision]))) +(defmacro has-form [expr form] + `(is (= ~form (core/-form ~expr)))) + + (defmacro testing-constant-form [elm-constructor] (let [form-name (symbol (name elm-constructor))] `(testing "form" - (let [compile-ctx# {:library {:parameters {:def [{:name "x"}]}}} - elm# ~elm-constructor - expr# (c/compile compile-ctx# elm#)] - (is (= (quote ~form-name) (core/-form expr#))))))) + (let [expr# (dynamic-compile ~elm-constructor)] + (has-form expr# (quote ~form-name)))))) -(defmacro testing-unary-form [elm-constructor] +(defmacro testing-unary-form + "Works with unary and aggregate operators." + [elm-constructor] (let [form-name (symbol (name elm-constructor))] `(testing "form" - (let [compile-ctx# {:library {:parameters {:def [{:name "x"}]}}} - elm# (~elm-constructor (elm/parameter-ref "x")) - expr# (c/compile compile-ctx# elm#)] - (is (= (quote (~form-name (~'param-ref "x"))) (core/-form expr#))))))) + (let [elm# (~elm-constructor (elm/parameter-ref "x")) + expr# (dynamic-compile elm#)] + (has-form expr# '(~form-name (~'param-ref "x"))))))) (defmacro testing-unary-precision-form @@ -187,23 +224,21 @@ ([elm-constructor & precisions] (let [form-name (symbol (name elm-constructor))] `(testing "form" - (let [compile-ctx# {:library {:parameters {:def [{:name "x"}]}}}] - (doseq [precision# ~(vec precisions)] - (let [elm# (~elm-constructor [(elm/parameter-ref "x") precision#]) - expr# (c/compile compile-ctx# elm#)] - (is (= (list '~form-name '(~'param-ref "x") precision#) - (core/-form expr#)))))))))) + (doseq [precision# ~(vec precisions)] + (let [elm# (~elm-constructor [(elm/parameter-ref "x") precision#]) + expr# (dynamic-compile elm#)] + (has-form expr# + (list '~form-name '(~'param-ref "x") precision#)))))))) (defmacro testing-binary-form [elm-constructor] (let [form-name (symbol (name elm-constructor))] `(testing "form" - (let [compile-ctx# {:library {:parameters {:def [{:name "x"} {:name "y"}]}}} - elm# (~elm-constructor [(elm/parameter-ref "x") + (let [elm# (~elm-constructor [(elm/parameter-ref "x") (elm/parameter-ref "y")]) - expr# (c/compile compile-ctx# elm#)] - (is (= (quote (~form-name (~'param-ref "x") (~'param-ref "y"))) - (core/-form expr#))))))) + expr# (dynamic-compile elm#)] + (has-form expr# + (quote (~form-name (~'param-ref "x") (~'param-ref "y")))))))) (defmacro testing-binary-precision-form @@ -212,10 +247,71 @@ ([elm-constructor & precisions] (let [form-name (symbol (name elm-constructor))] `(testing "form" - (let [compile-ctx# {:library {:parameters {:def [{:name "x"} {:name "y"}]}}}] - (doseq [precision# ~(vec precisions)] - (let [elm# (~elm-constructor [(elm/parameter-ref "x") - (elm/parameter-ref "y") precision#]) - expr# (c/compile compile-ctx# elm#)] - (is (= (list '~form-name '(~'param-ref "x") '(~'param-ref "y") - precision#) (core/-form expr#)))))))))) + (doseq [precision# ~(vec precisions)] + (let [elm# (~elm-constructor [(elm/parameter-ref "x") + (elm/parameter-ref "y") precision#]) + expr# (dynamic-compile elm#)] + (has-form expr# + (list '~form-name '(~'param-ref "x") '(~'param-ref "y") precision#)))))))) + + +(defmacro testing-ternary-form [elm-constructor] + (let [form-name (symbol (name elm-constructor))] + `(testing "form" + (let [elm# (~elm-constructor [(elm/parameter-ref "x") + (elm/parameter-ref "y") + (elm/parameter-ref "z")]) + expr# (dynamic-compile elm#)] + (has-form expr# + (quote (~form-name (~'param-ref "x") (~'param-ref "y") (~'param-ref "z")))))))) + + +(defn with-locator [constructor locator] + (comp #(assoc % :locator locator) constructor)) + + +(defmacro testing-constant-dynamic [elm-constructor] + `(testing "expression is dynamic" + (is (false? (core/-static (dynamic-compile ~elm-constructor)))))) + + +(defmacro testing-unary-dynamic [elm-constructor] + `(testing "expression is dynamic" + (is (false? (core/-static (dynamic-compile (~elm-constructor + #elm/parameter-ref "x"))))))) + + +(defmacro testing-unary-precision-dynamic + [elm-constructor & precisions] + `(testing "expression is dynamic" + (doseq [precision# ~(vec precisions)] + (is (false? (core/-static (dynamic-compile (~elm-constructor + [(elm/parameter-ref "x") + precision#])))))))) + + +(defmacro testing-binary-dynamic [elm-constructor] + `(testing "expression is dynamic" + (is (false? (core/-static (dynamic-compile (~elm-constructor + [#elm/parameter-ref "x" + #elm/parameter-ref "y"]))))))) + + +(defmacro testing-binary-precision-dynamic + ([elm-constructor] + `(testing-binary-precision-dynamic ~elm-constructor "year" "month")) + ([elm-constructor & precisions] + `(testing "expression is dynamic" + (doseq [precision# ~(vec precisions)] + (is (false? (core/-static (dynamic-compile (~elm-constructor + [(elm/parameter-ref "x") + (elm/parameter-ref "y") + precision#]))))))))) + + +(defmacro testing-ternary-dynamic [elm-constructor] + `(testing "expression is dynamic" + (is (false? (core/-static (dynamic-compile (~elm-constructor + [#elm/parameter-ref "x" + #elm/parameter-ref "y" + #elm/parameter-ref "z"]))))))) diff --git a/modules/cql/test/blaze/elm/compiler/type_operators_test.clj b/modules/cql/test/blaze/elm/compiler/type_operators_test.clj index 4a9402bf2..4763c58e6 100644 --- a/modules/cql/test/blaze/elm/compiler/type_operators_test.clj +++ b/modules/cql/test/blaze/elm/compiler/type_operators_test.clj @@ -8,6 +8,7 @@ [blaze.elm.compiler :as c] [blaze.elm.compiler.clinical-operators] [blaze.elm.compiler.core :as core] + [blaze.elm.compiler.core-spec] [blaze.elm.compiler.test-util :as tu] [blaze.elm.compiler.type-operators] [blaze.elm.concept :as concept] @@ -49,58 +50,58 @@ (testing "FHIR types" (are [elm resource res] (= res (core/-eval (c/compile {} elm) {} nil {"R" resource})) #elm/as ["{http://hl7.org/fhir}boolean" - {:path "deceased" - :scope "R" - :type "Property"}] + {:path "deceased" + :scope "R" + :type "Property"}] {:fhir/type :fhir/Patient :id "0" :deceased true} true #elm/as ["{http://hl7.org/fhir}integer" - {:path "value" - :scope "R" - :type "Property"}] + {:path "value" + :scope "R" + :type "Property"}] {:fhir/type :fhir/Observation :value (int 1)} (int 1) #elm/as ["{http://hl7.org/fhir}string" - {:path "name" - :scope "R" - :type "Property"}] + {:path "name" + :scope "R" + :type "Property"}] {:fhir/type :fhir/Account :name "a"} "a" #elm/as ["{http://hl7.org/fhir}decimal" - {:path "duration" - :scope "R" - :type "Property"}] + {:path "duration" + :scope "R" + :type "Property"}] {:fhir/type :fhir/Media :duration 1.1M} 1.1M #elm/as ["{http://hl7.org/fhir}uri" - {:path "url" - :scope "R" - :type "Property"}] + {:path "url" + :scope "R" + :type "Property"}] {:fhir/type :fhir/Measure :url #fhir/uri"a"} #fhir/uri"a" #elm/as ["{http://hl7.org/fhir}url" - {:path "address" - :scope "R" - :type "Property"}] + {:path "address" + :scope "R" + :type "Property"}] {:fhir/type :fhir/Endpoint :address #fhir/url"a"} #fhir/url"a" #elm/as ["{http://hl7.org/fhir}dateTime" - {:path "value" - :scope "R" - :type "Property"}] + {:path "value" + :scope "R" + :type "Property"}] {:fhir/type :fhir/Observation :value #fhir/dateTime"2019-09-04"} #fhir/dateTime"2019-09-04" #elm/as ["{http://hl7.org/fhir}Quantity" - {:path "value" - :scope "R" - :type "Property"}] + {:path "value" + :scope "R" + :type "Property"}] {:fhir/type :fhir/Observation :value #fhir/dateTime"2019-09-04"} nil)) @@ -118,8 +119,13 @@ #elm/as ["{urn:hl7-org:elm-types:r1}DateTime" #elm/date-time"2019-09-04"] (system/date-time 2019 9 4))) + (testing "expression is dynamic" + (is (false? (core/-static (tu/dynamic-compile + #elm/as["{urn:hl7-org:elm-types:r1}Integer" + #elm/parameter-ref "x"]))))) + (testing "form" - (are [elm form] (= form (core/-form (c/compile {} elm))) + (are [elm form] (= form (c/form (c/compile {} elm))) #elm/as ["{urn:hl7-org:elm-types:r1}Integer" {:type "Null"}] nil @@ -127,9 +133,9 @@ '(as elm/integer 1) #elm/as ["{http://hl7.org/fhir}dateTime" - {:path "value" - :scope "R" - :type "Property"}] + {:path "value" + :scope "R" + :type "Property"}] '(as fhir/dateTime (:value R)) {:type "As" @@ -194,11 +200,9 @@ (tu/testing-binary-null elm/can-convert-quantity #elm/quantity [1 "m"] #elm/string "m") - (testing "form" - (let [compile-ctx {:library {:parameters {:def [{:name "q"}]}}} - elm #elm/can-convert-quantity[#elm/parameter-ref "q" #elm/string "g"] - expr (c/compile compile-ctx elm)] - (is (= '(can-convert-quantity (param-ref "q") "g") (core/-form expr)))))) + (tu/testing-binary-dynamic elm/can-convert-quantity) + + (tu/testing-binary-form elm/can-convert-quantity)) ;; 22.4. Children @@ -220,7 +224,11 @@ ;; TODO: other types - (tu/testing-unary-null elm/children)) + (tu/testing-unary-null elm/children) + + (tu/testing-unary-dynamic elm/children) + + (tu/testing-unary-form elm/children)) ;; TODO 22.5. Convert @@ -274,11 +282,9 @@ (tu/testing-binary-null elm/convert-quantity #elm/quantity [5 "mg"] #elm/string "m") - (testing "form" - (let [compile-ctx {:library {:parameters {:def [{:name "q"}]}}} - elm #elm/convert-quantity[#elm/parameter-ref "q" #elm/string "g"] - expr (c/compile compile-ctx elm)] - (is (= '(convert-quantity (param-ref "q") "g") (core/-form expr)))))) + (tu/testing-binary-dynamic elm/convert-quantity) + + (tu/testing-binary-form elm/convert-quantity)) ;; 22.7. ConvertsToBoolean @@ -330,7 +336,7 @@ "bar" "")) - (testing "integer" + (testing "Integer" (is (true? (tu/compile-unop elm/converts-to-boolean elm/integer "1"))) (is (true? (tu/compile-unop elm/converts-to-boolean elm/integer "0"))) @@ -339,7 +345,7 @@ "2" "-1")) - (testing "long" + (testing "Long" (is (true? (tu/compile-unop elm/converts-to-boolean elm/long "1"))) (is (true? (tu/compile-unop elm/converts-to-boolean elm/long "0"))) @@ -348,7 +354,7 @@ "2" "-1")) - (testing "decimal" + (testing "Decimal" (are [x] (true? (tu/compile-unop elm/converts-to-boolean elm/decimal x)) "1" "1.0" @@ -366,22 +372,21 @@ "1.1" "0.9")) - (testing "boolean" + (testing "Boolean" (is (true? (tu/compile-unop elm/converts-to-boolean elm/boolean "true"))) (is (true? (tu/compile-unop elm/converts-to-boolean elm/boolean "false")))) - (testing "dynamic" + (testing "Dynamic" (are [x res] (= res (tu/dynamic-compile-eval (elm/converts-to-boolean x))) #elm/parameter-ref "A" false)) (tu/testing-unary-null elm/converts-to-boolean) - (testing "form" - (let [compile-ctx {:library {:parameters {:def [{:name "x"}]}}} - elm #elm/converts-to-boolean #elm/parameter-ref "x" - expr (c/compile compile-ctx elm)] - (is (= '(converts-to-boolean (param-ref "x")) (core/-form expr)))))) + (tu/testing-unary-dynamic elm/converts-to-boolean) + + (tu/testing-unary-form elm/converts-to-boolean)) + ;; 22.8. ConvertsToDate ;; @@ -435,6 +440,8 @@ (tu/testing-unary-null elm/converts-to-date) + (tu/testing-unary-dynamic elm/converts-to-date) + (tu/testing-unary-form elm/converts-to-date)) @@ -483,10 +490,12 @@ "2020" "2020-03" "2020-03-08" - "2020-03-08T12:13" ))) + "2020-03-08T12:13"))) (tu/testing-unary-null elm/converts-to-date-time) + (tu/testing-unary-dynamic elm/converts-to-date-time) + (tu/testing-unary-form elm/converts-to-date-time)) @@ -538,7 +547,7 @@ (are [x] (true? (tu/compile-unop elm/converts-to-decimal elm/decimal x)) "1.1")) - (testing "dynamic" + (testing "Dynamic" (are [x] (false? (tu/dynamic-compile-eval (elm/converts-to-decimal x))) #elm/parameter-ref "A") (are [x] (true? (tu/dynamic-compile-eval (elm/converts-to-decimal x))) @@ -546,11 +555,9 @@ (tu/testing-unary-null elm/converts-to-decimal) - (testing "form" - (let [compile-ctx {:library {:parameters {:def [{:name "x"}]}}} - elm #elm/converts-to-decimal #elm/parameter-ref "x" - expr (c/compile compile-ctx elm)] - (is (= '(converts-to-decimal (param-ref "x")) (core/-form expr)))))) + (tu/testing-unary-dynamic elm/converts-to-decimal) + + (tu/testing-unary-form elm/converts-to-decimal)) ;; 22.11. ConvertsToLong @@ -598,7 +605,7 @@ (are [x] (true? (tu/compile-unop elm/converts-to-long elm/long x)) "1")) - (testing "dynamic" + (testing "Dynamic" (are [x] (false? (tu/dynamic-compile-eval (elm/converts-to-long x))) #elm/parameter-ref "A") (are [x] (true? (tu/dynamic-compile-eval (elm/converts-to-long x))) @@ -606,11 +613,9 @@ (tu/testing-unary-null elm/converts-to-long) - (testing "form" - (let [compile-ctx {:library {:parameters {:def [{:name "x"}]}}} - elm #elm/converts-to-long #elm/parameter-ref "x" - expr (c/compile compile-ctx elm)] - (is (= '(converts-to-long (param-ref "x")) (core/-form expr)))))) + (tu/testing-unary-dynamic elm/converts-to-long) + + (tu/testing-unary-form elm/converts-to-long)) ;; 22.12. ConvertsToInteger @@ -657,7 +662,7 @@ (are [x] (true? (tu/compile-unop elm/converts-to-integer elm/integer x)) "1")) - (testing "dynamic" + (testing "Dynamic" (are [x] (false? (tu/dynamic-compile-eval (elm/converts-to-integer x))) #elm/parameter-ref "A") (are [x] (true? (tu/dynamic-compile-eval (elm/converts-to-integer x))) @@ -665,11 +670,9 @@ (tu/testing-unary-null elm/converts-to-integer) - (testing "form" - (let [compile-ctx {:library {:parameters {:def [{:name "x"}]}}} - elm #elm/converts-to-integer #elm/parameter-ref "x" - expr (c/compile compile-ctx elm)] - (is (= '(converts-to-integer (param-ref "x")) (core/-form expr)))))) + (tu/testing-unary-dynamic elm/converts-to-integer) + + (tu/testing-unary-form elm/converts-to-integer)) ;; 22.13. ConvertsToQuantity @@ -732,7 +735,7 @@ [[1 "m"] [1 "s"]] [[10 "s"] [1 "s"]])) - (testing "dynamic" + (testing "Dynamic" (are [x] (false? (tu/dynamic-compile-eval (elm/converts-to-quantity x))) #elm/parameter-ref "A") (are [x] (true? (tu/dynamic-compile-eval (elm/converts-to-quantity x))) @@ -740,11 +743,9 @@ (tu/testing-unary-null elm/converts-to-quantity) - (testing "form" - (let [compile-ctx {:library {:parameters {:def [{:name "x"}]}}} - elm #elm/converts-to-quantity #elm/parameter-ref "x" - expr (c/compile compile-ctx elm)] - (is (= '(converts-to-quantity (param-ref "x")) (core/-form expr)))))) + (tu/testing-unary-dynamic elm/converts-to-quantity) + + (tu/testing-unary-form elm/converts-to-quantity)) ;; 22.14. ConvertsToRatio @@ -775,17 +776,15 @@ "a" "0'm';0'm'")) - (testing "dynamic" + (testing "Dynamic" (are [x] (false? (tu/dynamic-compile-eval (elm/converts-to-ratio x))) #elm/parameter-ref "A")) (tu/testing-unary-null elm/converts-to-ratio) - (testing "form" - (let [compile-ctx {:library {:parameters {:def [{:name "x"}]}}} - elm #elm/converts-to-ratio #elm/parameter-ref "x" - expr (c/compile compile-ctx elm)] - (is (= '(converts-to-ratio (param-ref "x")) (core/-form expr)))))) + (tu/testing-unary-dynamic elm/converts-to-ratio) + + (tu/testing-unary-form elm/converts-to-ratio)) ;; 22.15. ConvertsToString @@ -852,17 +851,16 @@ (are [x] (false? (c/compile {} (elm/converts-to-string (elm/tuple x)))) {"foo" #elm/integer "1"})) - (testing "dynamic" + (testing "Dynamic" (are [x] (true? (tu/dynamic-compile-eval (elm/converts-to-string x))) #elm/parameter-ref "A")) (tu/testing-unary-null elm/converts-to-string) - (testing "form" - (let [compile-ctx {:library {:parameters {:def [{:name "x"}]}}} - elm #elm/converts-to-string #elm/parameter-ref "x" - expr (c/compile compile-ctx elm)] - (is (= '(converts-to-string (param-ref "x")) (core/-form expr)))))) + (tu/testing-unary-dynamic elm/converts-to-string) + + (tu/testing-unary-form elm/converts-to-string)) + ;; 22.16. ConvertsToTime ;; @@ -888,13 +886,17 @@ ;; ;; If the argument is null, the result is null. (deftest compile-converts-to-time-test - (let [eval #(core/-eval % {:now tu/now} nil nil)] + (let [compile (partial tu/compile-unop elm/converts-to-time) + eval #(core/-eval % {:now tu/now} nil nil)] (testing "String" - (are [x] (true? (eval (tu/compile-unop elm/converts-to-time elm/string x))) + (testing "expression is dynamic" + (is (not (core/static? (compile elm/string ""))))) + + (are [x] (true? (eval (compile elm/string x))) "12:54:30" "12:54:30.010") - (are [x] (false? (eval (tu/compile-unop elm/converts-to-time elm/string x))) + (are [x] (false? (eval (compile elm/string x))) "aaaa" "12:54" "24:54:00" @@ -902,23 +904,31 @@ "14-30-00.0")) (testing "Time" - (are [x] (true? (eval (tu/compile-unop elm/converts-to-time elm/time x))) + (testing "expression is dynamic" + (is (not (core/static? (compile elm/time "12:54"))))) + + (are [x] (true? (eval (compile elm/time x))) "12:54" "12:54:00" "12:54:30.010")) (testing "DateTime" - (are [x] (true? (eval (tu/compile-unop elm/converts-to-time elm/date-time x))) + (testing "expression is dynamic" + (is (not (core/static? (compile elm/string "2020-03-08T12:54:00"))))) + + (are [x] (true? (eval (compile elm/date-time x))) "2020-03-08T12:54:00" "2020-03-08T12:54:30.010")) - (testing "dynamic" + (testing "Dynamic" (are [x] (true? (tu/dynamic-compile-eval (elm/converts-to-time x))) #elm/parameter-ref "12:54:00" #elm/parameter-ref "2020-01-02T03:04:05.006Z"))) (tu/testing-unary-null elm/converts-to-time) + (tu/testing-unary-dynamic elm/converts-to-time) + (tu/testing-unary-form elm/converts-to-time)) @@ -934,6 +944,9 @@ ;; If the source is null, the result is null. (deftest compile-to-descendents-test (testing "Code" + (testing "expression is dynamic" + (is (not (core/static? (c/compile {} (elm/descendents (tu/code "system-134534" "code-134551"))))))) + (are [x res] (= res (core/-eval (c/compile {} (elm/descendents x)) {:now tu/now} nil nil)) (tu/code "system-134534" "code-134551") @@ -941,7 +954,11 @@ ;; TODO: other types - (tu/testing-unary-null elm/descendents)) + (tu/testing-unary-null elm/descendents) + + (tu/testing-unary-dynamic elm/descendents) + + (tu/testing-unary-form elm/descendents)) ;; 22.18. Is @@ -1087,8 +1104,13 @@ #elm/is ["{urn:hl7-org:elm-types:r1}DateTime" #elm/string "2019-09-04"] #elm/is ["{urn:hl7-org:elm-types:r1}DateTime" {:type "Null"}])) + (testing "expression is dynamic" + (is (false? (core/-static (tu/dynamic-compile + #elm/is["{urn:hl7-org:elm-types:r1}Integer" + #elm/parameter-ref "x"]))))) + (testing "form" - (are [elm form] (= form (core/-form (c/compile {} elm))) + (are [elm form] (= form (c/form (c/compile {} elm))) #elm/is ["{urn:hl7-org:elm-types:r1}Integer" {:type "Null"}] '(is elm/integer nil) @@ -1131,88 +1153,88 @@ ;; ;; If the argument is null the result is null. (deftest compile-to-boolean-test - (testing "String" - (are [x] (true? (tu/compile-unop elm/to-boolean elm/string x)) - "true" - "t" - "yes" - "y" - "1" - "True" - "T" - "TRUE" - "YES" - "Yes" - "Y") - - (are [x] (false? (tu/compile-unop elm/to-boolean elm/string x)) - "false" - "f" - "no" - "n" - "0" - "False" - "F" - "FALSE" - "NO" - "No" - "N") - - (are [x] (nil? (tu/compile-unop elm/to-boolean elm/string x)) - "foo" - "bar" - "")) - - (testing "integer" - (is (true? (tu/compile-unop elm/to-boolean elm/integer "1"))) - - (is (false? (tu/compile-unop elm/to-boolean elm/integer "0"))) - - (are [x] (nil? (tu/compile-unop elm/to-boolean elm/integer x)) - "2" - "-1")) - - (testing "long" - (is (true? (tu/compile-unop elm/to-boolean elm/long "1"))) - - (is (false? (tu/compile-unop elm/to-boolean elm/long "0"))) - - (are [x] (nil? (tu/compile-unop elm/to-boolean elm/long x)) - "2" - "-1")) - - (testing "decimal" - (are [x] (true? (tu/compile-unop elm/to-boolean elm/decimal x)) - "1" - "1.0" - "1.00" - "1.00000000") - - (are [x] (false? (tu/compile-unop elm/to-boolean elm/decimal x)) - "0" - "0.0" - "0.00" - "0.00000000") - - (are [x] (nil? (tu/compile-unop elm/to-boolean elm/decimal x)) - "0.1" - "-1.0" - "2.0" - "1.1" - "0.9")) - - (testing "boolean" - (is (true? (tu/compile-unop elm/to-boolean elm/boolean "true"))) + (testing "Static" + (testing "String" + (are [x] (true? (tu/compile-unop elm/to-boolean elm/string x)) + "true" + "t" + "yes" + "y" + "1" + "True" + "T" + "TRUE" + "YES" + "Yes" + "Y") + + (are [x] (false? (tu/compile-unop elm/to-boolean elm/string x)) + "false" + "f" + "no" + "n" + "0" + "False" + "F" + "FALSE" + "NO" + "No" + "N") + + (are [x] (nil? (tu/compile-unop elm/to-boolean elm/string x)) + "foo" + "bar" + "")) + + (testing "Integer" + (is (true? (tu/compile-unop elm/to-boolean elm/integer "1"))) + + (is (false? (tu/compile-unop elm/to-boolean elm/integer "0"))) + + (are [x] (nil? (tu/compile-unop elm/to-boolean elm/integer x)) + "2" + "-1")) + + (testing "Long" + (is (true? (tu/compile-unop elm/to-boolean elm/long "1"))) + + (is (false? (tu/compile-unop elm/to-boolean elm/long "0"))) + + (are [x] (nil? (tu/compile-unop elm/to-boolean elm/long x)) + "2" + "-1")) + + (testing "Decimal" + (are [x] (true? (tu/compile-unop elm/to-boolean elm/decimal x)) + "1" + "1.0" + "1.00" + "1.00000000") + + (are [x] (false? (tu/compile-unop elm/to-boolean elm/decimal x)) + "0" + "0.0" + "0.00" + "0.00000000") + + (are [x] (nil? (tu/compile-unop elm/to-boolean elm/decimal x)) + "0.1" + "-1.0" + "2.0" + "1.1" + "0.9")) + + (testing "Boolean" + (is (true? (tu/compile-unop elm/to-boolean elm/boolean "true"))) + + (is (false? (tu/compile-unop elm/to-boolean elm/boolean "false"))))) - (is (false? (tu/compile-unop elm/to-boolean elm/boolean "false")))) (tu/testing-unary-null elm/to-boolean) - (testing "form" - (let [compile-ctx {:library {:parameters {:def [{:name "x"}]}}} - elm #elm/to-boolean #elm/parameter-ref "x" - expr (c/compile compile-ctx elm)] - (is (= '(to-boolean (param-ref "x")) (core/-form expr)))))) + (tu/testing-unary-dynamic elm/to-boolean) + + (tu/testing-unary-form elm/to-boolean)) ;; 22.20. ToChars @@ -1231,9 +1253,9 @@ (testing "Integer" (are [x] (nil? (tu/compile-unop elm/to-chars elm/integer x)) - "1" )) + "1")) - (testing "dynamic" + (testing "Dynamic" (are [x res] (= res (tu/dynamic-compile-eval (elm/to-chars x))) #elm/parameter-ref "A" '("A") #elm/parameter-ref "ab" '("a" "b") @@ -1241,11 +1263,10 @@ (tu/testing-unary-null elm/to-chars) - (testing "form" - (let [compile-ctx {:library {:parameters {:def [{:name "x"}]}}} - elm #elm/to-chars #elm/parameter-ref "x" - expr (c/compile compile-ctx elm)] - (is (= '(to-chars (param-ref "x")) (core/-form expr)))))) + (tu/testing-unary-dynamic elm/to-chars) + + (tu/testing-unary-form elm/to-chars)) + ;; 22.21. ToConcept ;; @@ -1272,11 +1293,9 @@ (tu/testing-unary-null elm/to-concept) - (testing "form" - (let [compile-ctx {:library {:parameters {:def [{:name "x"}]}}} - elm #elm/to-concept #elm/parameter-ref "x" - expr (c/compile compile-ctx elm)] - (is (= '(to-concept (param-ref "x")) (core/-form expr)))))) + (tu/testing-unary-dynamic elm/to-concept) + + (tu/testing-unary-form elm/to-concept)) ;; 22.22. ToDate @@ -1300,9 +1319,13 @@ ;; ;; If the argument is null, the result is null. (deftest compile-to-date-test - (let [eval #(core/-eval % {:now tu/now} nil nil)] + (let [compile (partial tu/compile-unop elm/to-date) + eval #(core/-eval % {:now tu/now} nil nil)] (testing "String" - (are [x res] (= res (eval (tu/compile-unop elm/to-date elm/string x))) + (testing "expression is dynamic" + (is (not (core/static? (compile elm/string ""))))) + + (are [x res] (= res (eval (compile elm/string x))) "2019" #system/date"2019" "2019-01" #system/date"2019-01" "2019-01-01" #system/date"2019-01-01" @@ -1312,13 +1335,20 @@ "2019-02-29" nil)) (testing "Date" - (are [x res] (= res (eval (tu/compile-unop elm/to-date elm/date x))) - "2019" #system/date"2019" - "2019-01" #system/date"2019-01" - "2019-01-01" #system/date"2019-01-01")) + (testing "Static" + (testing "expression is static" + (is (core/static? (compile elm/date "2023")))) + + (are [x res] (= res (compile elm/date x)) + "2020" #system/date"2020" + "2020-03" #system/date"2020-03" + "2020-03-08" #system/date"2020-03-08"))) (testing "DateTime" - (are [x res] (= res (eval (tu/compile-unop elm/to-date elm/date-time x))) + (testing "expression is dynamic" + (is (not (core/static? (compile elm/string "2019"))))) + + (are [x res] (= res (eval (compile elm/date-time x))) "2019" #system/date"2019" "2019-01" #system/date"2019-01" "2019-01-01" #system/date"2019-01-01" @@ -1326,7 +1356,7 @@ "2019-01-01T12:13:14" #system/date"2019-01-01" "2019-01-01T12:13:14.000-01:00" #system/date"2019-01-01") - (testing "dynamic" + (testing "Dynamic" (let [compile-ctx {:library {:parameters {:def [{:name "x"}]}}} elm #elm/to-date #elm/parameter-ref "x" expr (c/compile compile-ctx elm) @@ -1340,7 +1370,11 @@ #system/date-time"2023-05-07T16:07:00" #system/date"2023-05-07" #system/date-time"2023-05-07T16:07:00+02:00" #system/date"2023-05-07"))))) - (tu/testing-unary-null elm/to-date)) + (tu/testing-unary-null elm/to-date) + + (tu/testing-unary-dynamic elm/to-date) + + (tu/testing-unary-form elm/to-date)) ;; 22.23. ToDateTime @@ -1368,9 +1402,13 @@ ;; ;; If the argument is null, the result is null. (deftest compile-to-date-time-test - (let [eval #(core/-eval % {:now tu/now} nil nil)] + (let [compile (partial tu/compile-unop elm/to-date-time) + eval #(core/-eval % {:now tu/now} nil nil)] (testing "String" - (are [x res] (= res (eval (tu/compile-unop elm/to-date-time elm/string x))) + (testing "expression is dynamic" + (is (not (core/static? (compile elm/string ""))))) + + (are [x res] (= res (eval (compile elm/string x))) "2020" #system/date-time"2020" "2020-03" #system/date-time"2020-03" "2020-03-08" #system/date-time"2020-03-08" @@ -1384,13 +1422,16 @@ (testing "Date" (testing "Static" - (are [x res] (= res (tu/compile-unop elm/to-date-time elm/date x)) + (testing "expression is static" + (is (core/static? (compile elm/date "2023")))) + + (are [x res] (= res (compile elm/date x)) "2020" #system/date-time"2020" "2020-03" #system/date-time"2020-03" "2020-03-08" #system/date-time"2020-03-08"))) (testing "DateTime" - (are [x res] (= res (eval (tu/compile-unop elm/to-date-time elm/date-time x))) + (are [x res] (= res (eval (compile elm/date-time x))) "2020" #system/date-time"2020" "2020-03" #system/date-time"2020-03" "2020-03-08" #system/date-time"2020-03-08" @@ -1398,6 +1439,8 @@ (tu/testing-unary-null elm/to-date-time) + (tu/testing-unary-dynamic elm/to-date-time) + (tu/testing-unary-form elm/to-date-time)) @@ -1447,11 +1490,9 @@ (tu/testing-unary-null elm/to-decimal) - (testing "form" - (let [compile-ctx {:library {:parameters {:def [{:name "x"}]}}} - elm #elm/to-decimal #elm/parameter-ref "x" - expr (c/compile compile-ctx elm)] - (is (= '(to-decimal (param-ref "x")) (core/-form expr)))))) + (tu/testing-unary-dynamic elm/to-decimal) + + (tu/testing-unary-form elm/to-decimal)) ;; 22.25. ToInteger @@ -1493,11 +1534,9 @@ (tu/testing-unary-null elm/to-integer) - (testing "form" - (let [compile-ctx {:library {:parameters {:def [{:name "x"}]}}} - elm #elm/to-integer #elm/parameter-ref "x" - expr (c/compile compile-ctx elm)] - (is (= '(to-integer (param-ref "x")) (core/-form expr)))))) + (tu/testing-unary-dynamic elm/to-integer) + + (tu/testing-unary-form elm/to-integer)) ;; 22.26. ToList @@ -1513,22 +1552,26 @@ ;; ;; The operator is used to implement list promotion efficiently. (deftest compile-to-list-test - (testing "Boolean" - (are [x res] (= res (tu/compile-unop elm/to-list elm/boolean x)) - "false" [false])) + (testing "Static" + (testing "Boolean" + (are [x res] (= res (tu/compile-unop elm/to-list elm/boolean x)) + "false" [false])) - (testing "Integer" - (are [x res] (= res (tu/compile-unop elm/to-list elm/integer x)) - "1" [1])) + (testing "Integer" + (are [x res] (= res (tu/compile-unop elm/to-list elm/integer x)) + "1" [1])) - (testing "Null" - (is (= [] (c/compile {} #elm/to-list{:type "Null"})))) + (testing "Null" + (is (= [] (c/compile {} #elm/to-list{:type "Null"}))))) - (testing "form" - (let [compile-ctx {:library {:parameters {:def [{:name "x"}]}}} - elm #elm/to-list #elm/parameter-ref "x" - expr (c/compile compile-ctx elm)] - (is (= '(to-list (param-ref "x")) (core/-form expr)))))) + (testing "Dynamic" + (are [x res] (= res (tu/dynamic-compile-eval (elm/to-list x))) + #elm/parameter-ref "nil" [] + #elm/parameter-ref "a" ["a"])) + + (tu/testing-unary-dynamic elm/to-list) + + (tu/testing-unary-form elm/to-list)) ;; 22.27. ToLong @@ -1574,11 +1617,9 @@ (tu/testing-unary-null elm/to-long) - (testing "form" - (let [compile-ctx {:library {:parameters {:def [{:name "x"}]}}} - elm #elm/to-long #elm/parameter-ref "x" - expr (c/compile compile-ctx elm)] - (is (= '(to-long (param-ref "x")) (core/-form expr)))))) + (tu/testing-unary-dynamic elm/to-long) + + (tu/testing-unary-form elm/to-long)) ;; 22.28. ToQuantity @@ -1656,11 +1697,9 @@ (tu/testing-unary-null elm/to-quantity) - (testing "form" - (let [compile-ctx {:library {:parameters {:def [{:name "x"}]}}} - elm #elm/to-quantity #elm/parameter-ref "x" - expr (c/compile compile-ctx elm)] - (is (= '(to-quantity (param-ref "x")) (core/-form expr)))))) + (tu/testing-unary-dynamic elm/to-quantity) + + (tu/testing-unary-form elm/to-quantity)) ;; 22.29. ToRatio @@ -1710,11 +1749,9 @@ (tu/testing-unary-null elm/to-ratio) - (testing "form" - (let [compile-ctx {:library {:parameters {:def [{:name "x"}]}}} - elm #elm/to-ratio #elm/parameter-ref "x" - expr (c/compile compile-ctx elm)] - (is (= '(to-ratio (param-ref "x")) (core/-form expr)))))) + (tu/testing-unary-dynamic elm/to-ratio) + + (tu/testing-unary-form elm/to-ratio)) ;; 22.30. ToString @@ -1792,11 +1829,9 @@ (tu/testing-unary-null elm/to-string) - (testing "form" - (let [compile-ctx {:library {:parameters {:def [{:name "x"}]}}} - elm #elm/to-string #elm/parameter-ref "x" - expr (c/compile compile-ctx elm)] - (is (= '(to-string (param-ref "x")) (core/-form expr)))))) + (tu/testing-unary-dynamic elm/to-string) + + (tu/testing-unary-form elm/to-string)) ;; 22.31. ToTime @@ -1847,9 +1882,13 @@ "2020-03-08T12:54:00" (system/time 12 54 00) "2020-03-08T12:54:30.010" (system/time 12 54 30 10))) - (testing "dynamic" + (testing "Dynamic" (are [x res] (= res (tu/dynamic-compile-eval (elm/to-time x))) #elm/parameter-ref "12:54:00" (system/time 12 54 00) #elm/parameter-ref "2020-01-02T03:04:05.006Z" (system/time 3 4 5 6)))) - (tu/testing-unary-null elm/to-time)) + (tu/testing-unary-null elm/to-time) + + (tu/testing-unary-dynamic elm/to-time) + + (tu/testing-unary-form elm/to-time)) diff --git a/modules/cql/test/blaze/elm/literal.clj b/modules/cql/test/blaze/elm/literal.clj index 148f47e1c..17aa8eff9 100644 --- a/modules/cql/test/blaze/elm/literal.clj +++ b/modules/cql/test/blaze/elm/literal.clj @@ -1,6 +1,6 @@ (ns blaze.elm.literal (:refer-clojure - :exclude [abs and boolean count distinct first flatten list long max min not or + :exclude [abs and boolean count distinct first flatten last list long max min not or time]) (:require [blaze.elm.spec] @@ -262,6 +262,7 @@ :element elements}) +;; 15.2. If (defn if-expr [[condition then else]] {:type "If" :condition condition :then then :else else}) @@ -355,12 +356,13 @@ ;; 16.19. Round -(defn round [[operand precision]] - (cond-> - {:type "Round" - :operand operand} - precision - (assoc :precision precision))) +(defn round [arg] + (let [[operand precision] (if (sequential? arg) arg [arg])] + (cond-> + {:type "Round" + :operand operand} + precision + (assoc :precision precision)))) ;; 16.20. Subtract @@ -402,6 +404,13 @@ :operand ops}) +;; 17.7. LastPositionOf +(defn last-position-of [[pattern s]] + {:type "LastPositionOf" + :pattern pattern + :string s}) + + ;; 17.8. Length (defn length [x] {:type "Length" @@ -420,6 +429,19 @@ :operand ops}) +;; 17.12. PositionOf +(defn position-of [[pattern s]] + {:type "PositionOf" + :pattern pattern + :string s}) + + +;; 17.13. ReplaceMatches +(defn replace-matches [ops] + {:type "ReplaceMatches" + :operand ops}) + + ;; 17.16. StartsWith (defn starts-with [ops] {:type "StartsWith" @@ -535,6 +557,11 @@ millisecond (assoc :millisecond millisecond))))) +;; 18.21. TimeOfDay +(def time-of-day + {:type "TimeOfDay"}) + + ;; 18.22. Today (def today {:type "Today"}) @@ -716,7 +743,7 @@ ;; 20.3. Current (defn current [scope] - {:type "Current" :scope scope}) + (cond-> {:type "Current"} scope (assoc :scope scope))) ;; 20.4. Distinct @@ -739,6 +766,16 @@ {:type "Flatten" :operand list}) +;; 20.16. IndexOf +(defn index-of [[source element]] + {:type "IndexOf" :source source :element element}) + + +;; 20.18. Last +(defn last [source] + {:type "Last" :source source}) + + ;; 20.25. SingletonFrom (defn singleton-from [list] {:type "SingletonFrom" :operand list}) diff --git a/modules/cql/test/blaze/elm/literal_spec.clj b/modules/cql/test/blaze/elm/literal_spec.clj index b52d04117..a2cd8ca69 100644 --- a/modules/cql/test/blaze/elm/literal_spec.clj +++ b/modules/cql/test/blaze/elm/literal_spec.clj @@ -247,8 +247,9 @@ (s/fdef elm/round - :args (s/cat :ops (s/spec (s/cat :x :elm/expression - :precision (s/? :elm/expression)))) + :args (s/cat :ops (s/alt :single :elm/expression + :multi (s/spec (s/cat :x :elm/expression + :precision (s/? :elm/expression))))) :ret :elm/expression) @@ -413,7 +414,7 @@ ;; 20.3. Current (s/fdef elm/current - :args (s/cat :scope string?) + :args (s/cat :scope (s/nilable string?)) :ret :elm/expression) diff --git a/modules/cql/test/data_readers.clj b/modules/cql/test/data_readers.clj index 6b25344ae..0c90a6a8e 100644 --- a/modules/cql/test/data_readers.clj +++ b/modules/cql/test/data_readers.clj @@ -67,11 +67,28 @@ elm/interval blaze.elm.literal/interval elm/contains blaze.elm.literal/contains elm/intersect blaze.elm.literal/intersect + elm/point-from blaze.elm.literal/point-from elm/current blaze.elm.literal/current elm/distinct blaze.elm.literal/distinct elm/exists blaze.elm.literal/exists elm/first blaze.elm.literal/first + elm/last blaze.elm.literal/last elm/singleton-from blaze.elm.literal/singleton-from + elm/all-true blaze.elm.literal/all-true + elm/any-true blaze.elm.literal/any-true + elm/avg blaze.elm.literal/avg + elm/count blaze.elm.literal/count + elm/geometric-mean blaze.elm.literal/geometric-mean + elm/product blaze.elm.literal/product + elm/max blaze.elm.literal/max + elm/median blaze.elm.literal/median + elm/min blaze.elm.literal/min + elm/mode blaze.elm.literal/mode + elm/population-variance blaze.elm.literal/population-variance + elm/population-std-dev blaze.elm.literal/population-std-dev + elm/sum blaze.elm.literal/sum + elm/std-dev blaze.elm.literal/std-dev + elm/variance blaze.elm.literal/variance elm/as blaze.elm.literal/as elm/can-convert-quantity blaze.elm.literal/can-convert-quantity elm/convert-quantity blaze.elm.literal/convert-quantity diff --git a/modules/db-protocols/deps.edn b/modules/db-protocols/deps.edn index 5aeab72af..0967ef424 100644 --- a/modules/db-protocols/deps.edn +++ b/modules/db-protocols/deps.edn @@ -1 +1 @@ -{:deps {}} +{} diff --git a/modules/db-resource-store-cassandra/.clj-kondo/config.edn b/modules/db-resource-store-cassandra/.clj-kondo/config.edn index bed29afaa..884a543ed 100644 --- a/modules/db-resource-store-cassandra/.clj-kondo/config.edn +++ b/modules/db-resource-store-cassandra/.clj-kondo/config.edn @@ -1,6 +1,6 @@ {:lint-as {blaze.anomaly/when-ok clojure.core/let - blaze.test-util/with-system clojure.core/with-open + blaze.module.test-util/with-system clojure.core/with-open prometheus.alpha/defhistogram clojure.core/def} :linters @@ -21,6 +21,7 @@ :consistent-alias {:aliases - {cuerdas.core c-str}}} + {cognitect.anomalies anom + cuerdas.core c-str}}} :skip-comments true} diff --git a/modules/db-resource-store-cassandra/deps.edn b/modules/db-resource-store-cassandra/deps.edn index e9552c325..65cb5119a 100644 --- a/modules/db-resource-store-cassandra/deps.edn +++ b/modules/db-resource-store-cassandra/deps.edn @@ -19,8 +19,8 @@ {:extra-paths ["test"] :extra-deps - {blaze/test-util - {:local/root "../test-util"}}} + {blaze/fhir-test-util + {:local/root "../fhir-test-util"}}} :kaocha {:extra-deps diff --git a/modules/db-resource-store-cassandra/test/blaze/db/resource_store/cassandra_test.clj b/modules/db-resource-store-cassandra/test/blaze/db/resource_store/cassandra_test.clj index 66deb3bf1..1b06253f2 100644 --- a/modules/db-resource-store-cassandra/test/blaze/db/resource_store/cassandra_test.clj +++ b/modules/db-resource-store-cassandra/test/blaze/db/resource_store/cassandra_test.clj @@ -11,8 +11,10 @@ [blaze.fhir.hash :as hash] [blaze.fhir.hash-spec] [blaze.fhir.spec :as fhir-spec] + [blaze.fhir.test-util :refer [given-failed-future]] [blaze.log] - [blaze.test-util :as tu :refer [given-failed-future given-thrown with-system]] + [blaze.module.test-util :refer [with-system]] + [blaze.test-util :as tu :refer [given-thrown]] [clojure.spec.alpha :as s] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [deftest is testing]] @@ -22,10 +24,11 @@ [jsonista.core :as j] [taoensso.timbre :as log]) (:import - [com.datastax.oss.driver.api.core CqlSession DriverTimeoutException ConsistencyLevel] - [com.datastax.oss.driver.api.core.cql PreparedStatement BoundStatement - Statement Row AsyncResultSet SimpleStatement] - [com.datastax.oss.driver.api.core.metadata Node EndPoint] + [com.datastax.oss.driver.api.core + ConsistencyLevel CqlSession DriverTimeoutException] + [com.datastax.oss.driver.api.core.cql + AsyncResultSet BoundStatement PreparedStatement Row SimpleStatement Statement] + [com.datastax.oss.driver.api.core.metadata EndPoint Node] [com.datastax.oss.driver.api.core.servererrors WriteTimeoutException WriteType] [com.fasterxml.jackson.dataformat.cbor CBORFactory] [java.net InetSocketAddress] diff --git a/modules/db-resource-store/.clj-kondo/config.edn b/modules/db-resource-store/.clj-kondo/config.edn index bed29afaa..884a543ed 100644 --- a/modules/db-resource-store/.clj-kondo/config.edn +++ b/modules/db-resource-store/.clj-kondo/config.edn @@ -1,6 +1,6 @@ {:lint-as {blaze.anomaly/when-ok clojure.core/let - blaze.test-util/with-system clojure.core/with-open + blaze.module.test-util/with-system clojure.core/with-open prometheus.alpha/defhistogram clojure.core/def} :linters @@ -21,6 +21,7 @@ :consistent-alias {:aliases - {cuerdas.core c-str}}} + {cognitect.anomalies anom + cuerdas.core c-str}}} :skip-comments true} diff --git a/modules/db-resource-store/deps.edn b/modules/db-resource-store/deps.edn index 2ab2364cd..ea8611a00 100644 --- a/modules/db-resource-store/deps.edn +++ b/modules/db-resource-store/deps.edn @@ -22,8 +22,8 @@ {:extra-paths ["test"] :extra-deps - {blaze/test-util - {:local/root "../test-util"} + {blaze/fhir-test-util + {:local/root "../fhir-test-util"} criterium/criterium {:mvn/version "0.4.6"} diff --git a/modules/db-resource-store/test/blaze/db/resource_store/kv_test.clj b/modules/db-resource-store/test/blaze/db/resource_store/kv_test.clj index 52f6ecc4b..cfd7cf7cc 100644 --- a/modules/db-resource-store/test/blaze/db/resource_store/kv_test.clj +++ b/modules/db-resource-store/test/blaze/db/resource_store/kv_test.clj @@ -13,8 +13,10 @@ [blaze.fhir.hash :as hash] [blaze.fhir.hash-spec] [blaze.fhir.spec :as fhir-spec] + [blaze.fhir.test-util :refer [given-failed-future]] [blaze.metrics.spec] - [blaze.test-util :as tu :refer [given-failed-future given-thrown with-system]] + [blaze.module.test-util :refer [with-system]] + [blaze.test-util :as tu :refer [given-thrown]] [clojure.spec.alpha :as s] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [deftest is testing]] diff --git a/modules/db-stub/Makefile b/modules/db-stub/Makefile index c6dcaacb7..df75479db 100644 --- a/modules/db-stub/Makefile +++ b/modules/db-stub/Makefile @@ -1,6 +1,9 @@ lint: clj-kondo --lint src deps.edn +prep: + clojure -X:deps prep + test: true @@ -10,4 +13,4 @@ test-coverage: clean: rm -rf .clj-kondo/.cache .cpcache target -.PHONY: lint test test-coverage clean +.PHONY: lint prep test test-coverage clean diff --git a/modules/db-stub/deps.edn b/modules/db-stub/deps.edn index 5a37d1f21..ad0705478 100644 --- a/modules/db-stub/deps.edn +++ b/modules/db-stub/deps.edn @@ -2,5 +2,5 @@ {blaze/db {:local/root "../db"} - blaze/test-util - {:local/root "../test-util"}}} + blaze/fhir-test-util + {:local/root "../fhir-test-util"}}} diff --git a/modules/db-stub/src/blaze/db/api_stub.clj b/modules/db-stub/src/blaze/db/api_stub.clj index e619422e9..9c4123355 100644 --- a/modules/db-stub/src/blaze/db/api_stub.clj +++ b/modules/db-stub/src/blaze/db/api_stub.clj @@ -13,7 +13,8 @@ [blaze.db.tx-log :as tx-log] [blaze.db.tx-log-spec] [blaze.db.tx-log.local] - [blaze.test-util :refer [structure-definition-repo with-system]] + [blaze.fhir.test-util :refer [structure-definition-repo]] + [blaze.module.test-util :refer [with-system]] [integrant.core :as ig] [java-time.api :as time])) @@ -91,3 +92,9 @@ `(with-system [system# ~config] (run! #(deref (d/transact (:blaze.db/node system#) %)) ~txs) (let [~binding-form system#] ~@body))) + + +(defn extract-txs-body [more] + (if (vector? (first more)) + [(first more) (next more)] + [[] more])) diff --git a/modules/db-tx-log-kafka/.clj-kondo/config.edn b/modules/db-tx-log-kafka/.clj-kondo/config.edn index 2372f34e8..3010db42e 100644 --- a/modules/db-tx-log-kafka/.clj-kondo/config.edn +++ b/modules/db-tx-log-kafka/.clj-kondo/config.edn @@ -1,6 +1,6 @@ {:lint-as {blaze.anomaly/when-ok clojure.core/let - blaze.test-util/with-system clojure.core/with-open + blaze.module.test-util/with-system clojure.core/with-open prometheus.alpha/defcounter clojure.core/def prometheus.alpha/defhistogram clojure.core/def} diff --git a/modules/db-tx-log-kafka/deps.edn b/modules/db-tx-log-kafka/deps.edn index 6210ba92e..c47049c9a 100644 --- a/modules/db-tx-log-kafka/deps.edn +++ b/modules/db-tx-log-kafka/deps.edn @@ -15,15 +15,15 @@ {:local/root "../module-base"} org.apache.kafka/kafka-clients - {:mvn/version "3.5.0"}} + {:mvn/version "3.5.1"}} :aliases {:test {:extra-paths ["test"] :extra-deps - {blaze/test-util - {:local/root "../test-util"}}} + {blaze/fhir-test-util + {:local/root "../fhir-test-util"}}} :kaocha {:extra-deps diff --git a/modules/db-tx-log-kafka/test/blaze/db/tx_log/kafka/util_test.clj b/modules/db-tx-log-kafka/test/blaze/db/tx_log/kafka/util_test.clj index 268d672b9..d6a00693c 100644 --- a/modules/db-tx-log-kafka/test/blaze/db/tx_log/kafka/util_test.clj +++ b/modules/db-tx-log-kafka/test/blaze/db/tx_log/kafka/util_test.clj @@ -3,6 +3,7 @@ [blaze.db.tx-log.kafka.util :as u] [blaze.fhir.hash :as hash] [blaze.fhir.hash-spec] + [blaze.fhir.test-util] [blaze.test-util :as tu] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [deftest is testing]] @@ -10,10 +11,10 @@ [taoensso.timbre :as log]) (:import [java.time Instant] + [java.util Optional] [org.apache.kafka.clients.consumer ConsumerRecord] - [org.apache.kafka.common.record TimestampType] [org.apache.kafka.common.header.internals RecordHeaders] - [java.util Optional])) + [org.apache.kafka.common.record TimestampType])) (set! *warn-on-reflection* true) diff --git a/modules/db-tx-log-kafka/test/blaze/db/tx_log/kafka_test.clj b/modules/db-tx-log-kafka/test/blaze/db/tx_log/kafka_test.clj index bc5616e8d..bb99b6f40 100644 --- a/modules/db-tx-log-kafka/test/blaze/db/tx_log/kafka_test.clj +++ b/modules/db-tx-log-kafka/test/blaze/db/tx_log/kafka_test.clj @@ -6,8 +6,10 @@ [blaze.executors :as ex] [blaze.fhir.hash :as hash] [blaze.fhir.hash-spec] + [blaze.fhir.test-util :refer [given-failed-future]] [blaze.metrics.spec] - [blaze.test-util :as tu :refer [given-failed-future given-thrown with-system]] + [blaze.module.test-util :refer [with-system]] + [blaze.test-util :as tu :refer [given-thrown]] [clojure.spec.alpha :as s] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [deftest is testing]] diff --git a/modules/db-tx-log/deps.edn b/modules/db-tx-log/deps.edn index 1d1ca7aa0..1de6c30b4 100644 --- a/modules/db-tx-log/deps.edn +++ b/modules/db-tx-log/deps.edn @@ -16,8 +16,8 @@ {:extra-paths ["test"] :extra-deps - {blaze/test-util - {:local/root "../test-util"}}} + {blaze/fhir-test-util + {:local/root "../fhir-test-util"}}} :kaocha {:extra-deps diff --git a/modules/db-tx-log/test/blaze/db/tx_log/spec_test.clj b/modules/db-tx-log/test/blaze/db/tx_log/spec_test.clj index c3a8615e9..398c01260 100644 --- a/modules/db-tx-log/test/blaze/db/tx_log/spec_test.clj +++ b/modules/db-tx-log/test/blaze/db/tx_log/spec_test.clj @@ -3,6 +3,7 @@ [blaze.db.tx-log.spec] [blaze.fhir.hash :as hash] [blaze.fhir.hash-spec] + [blaze.fhir.test-util] [blaze.test-util :as tu] [clojure.spec.alpha :as s] [clojure.spec.test.alpha :as st] @@ -16,6 +17,7 @@ (test/use-fixtures :each tu/fixture) + (deftest t-test (are [x] (s/valid? :blaze.db/t x) 0 diff --git a/modules/db-tx-log/test/blaze/db/tx_log_test.clj b/modules/db-tx-log/test/blaze/db/tx_log_test.clj index 78f271bdf..fe331c42d 100644 --- a/modules/db-tx-log/test/blaze/db/tx_log_test.clj +++ b/modules/db-tx-log/test/blaze/db/tx_log_test.clj @@ -4,9 +4,10 @@ [blaze.db.tx-log :as tx-log] [blaze.fhir.hash :as hash] [blaze.fhir.hash-spec] + [blaze.fhir.test-util] [blaze.test-util :as tu] [clojure.spec.test.alpha :as st] - [clojure.test :as test :refer [is deftest]] + [clojure.test :as test :refer [deftest is]] [java-time.api :as time]) (:import [java.lang AutoCloseable] diff --git a/modules/db/.clj-kondo/config.edn b/modules/db/.clj-kondo/config.edn index 623d00fca..3d510f5ed 100644 --- a/modules/db/.clj-kondo/config.edn +++ b/modules/db/.clj-kondo/config.edn @@ -5,7 +5,7 @@ blaze.db.api-test-perf/with-system-data clojure.core/with-open blaze.db.impl.macros/with-open-coll clojure.core/with-open blaze.db.test-util/with-system-data clojure.core/with-open - blaze.test-util/with-system clojure.core/with-open + blaze.module.test-util/with-system clojure.core/with-open prometheus.alpha/defcounter clojure.core/def prometheus.alpha/defhistogram clojure.core/def} diff --git a/modules/db/build.clj b/modules/db/build.clj deleted file mode 100644 index 120695992..000000000 --- a/modules/db/build.clj +++ /dev/null @@ -1,11 +0,0 @@ -(ns build - (:refer-clojure :exclude [compile]) - (:require [clojure.tools.build.api :as b])) - - -(defn compile [_] - (b/javac - {:basis (b/create-basis {:project "deps.edn"}) - :src-dirs ["java"] - :class-dir "target/classes" - :javac-opts ["-Xlint:all" "-source" "11" "-target" "11"]})) diff --git a/modules/db/deps.edn b/modules/db/deps.edn index 882068b22..8023f0d6d 100644 --- a/modules/db/deps.edn +++ b/modules/db/deps.edn @@ -45,8 +45,8 @@ {:extra-paths ["test"] :extra-deps - {blaze/test-util - {:local/root "../test-util"}}} + {blaze/fhir-test-util + {:local/root "../fhir-test-util"}}} :kaocha {:extra-deps @@ -59,8 +59,8 @@ {:extra-paths ["test-perf"] :extra-deps - {blaze/test-util - {:local/root "../test-util"} + {blaze/fhir-test-util + {:local/root "../fhir-test-util"} criterium/criterium {:mvn/version "0.4.6"} diff --git a/modules/db/src/blaze/db/api.clj b/modules/db/src/blaze/db/api.clj index f41ab6181..cc921e3bc 100644 --- a/modules/db/src/blaze/db/api.clj +++ b/modules/db/src/blaze/db/api.clj @@ -75,6 +75,12 @@ (p/-as-of db t)) +(defn t + "Returns the effective `t` of `db`." + [db] + (or (p/-as-of-t db) (p/-basis-t db))) + + (defn basis-t "Returns the `t` of the most recent transaction reachable via `db`." [db] diff --git a/modules/db/src/blaze/db/api_spec.clj b/modules/db/src/blaze/db/api_spec.clj index c139353e1..daa16adee 100644 --- a/modules/db/src/blaze/db/api_spec.clj +++ b/modules/db/src/blaze/db/api_spec.clj @@ -31,6 +31,11 @@ :ret :blaze.db/node) +(s/fdef d/t + :args (s/cat :db :blaze.db/db) + :ret :blaze.db/t) + + (s/fdef d/basis-t :args (s/cat :db :blaze.db/db) :ret :blaze.db/t) diff --git a/modules/db/src/blaze/db/impl/codec.clj b/modules/db/src/blaze/db/impl/codec.clj index 63888db63..1ce913ce4 100644 --- a/modules/db/src/blaze/db/impl/codec.clj +++ b/modules/db/src/blaze/db/impl/codec.clj @@ -226,6 +226,7 @@ (defn id + "Creates an resource id as String from the byte array `id-bytes`." {:inline (fn [id-bytes offset length] `(String. ~id-bytes ~offset ~length StandardCharsets/ISO_8859_1))} @@ -266,6 +267,7 @@ ["_id" "_lastUpdated" "_profile" + "active" "address" "birthdate" "bodysite" diff --git a/modules/db/src/blaze/db/impl/index/resource_handle.clj b/modules/db/src/blaze/db/impl/index/resource_handle.clj index 748ebe3fd..9a5b1dba2 100644 --- a/modules/db/src/blaze/db/impl/index/resource_handle.clj +++ b/modules/db/src/blaze/db/impl/index/resource_handle.clj @@ -44,7 +44,9 @@ (unchecked-multiply-int 31) (unchecked-add-int (.hashCode id)) (unchecked-multiply-int 31) - (unchecked-add-int t)))) + (unchecked-add-int t))) + (toString [_] + (str (codec/tid->type tid) "[id = " id ", t = " t "]"))) (defn state->num-changes diff --git a/modules/db/src/blaze/db/impl/index/system_as_of.clj b/modules/db/src/blaze/db/impl/index/system_as_of.clj index 275e22839..9d2339bc6 100644 --- a/modules/db/src/blaze/db/impl/index/system_as_of.clj +++ b/modules/db/src/blaze/db/impl/index/system_as_of.clj @@ -35,7 +35,7 @@ (defn- decoder "Returns a function which decodes an resource handle out of a key and a value - byte buffers from the resource-as-of index. + byte buffers from the SystemAsOf index. Closes over a shared byte array for id decoding, because the String constructor creates a copy of the id bytes anyway. Can only be used from one diff --git a/modules/db/src/blaze/db/impl/search_param.clj b/modules/db/src/blaze/db/impl/search_param.clj index 907b09cf8..5da65c88c 100644 --- a/modules/db/src/blaze/db/impl/search_param.clj +++ b/modules/db/src/blaze/db/impl/search_param.clj @@ -146,18 +146,19 @@ linked-compartments)] (coll/eduction (mapcat - (fn index-entry [[modifier value]] + (fn index-entry [[modifier value include-in-compartments?]] (let [c-hash (c-hash-w-modifier c-hash code modifier)] (transduce - (map + (keep (fn index-compartment-entry [compartment] - (c-sp-vr/index-entry - compartment - c-hash - tid - value - id - hash))) + (when include-in-compartments? + (c-sp-vr/index-entry + compartment + c-hash + tid + value + id + hash)))) conj [(sp-vr/index-entry c-hash tid value id hash) (r-sp-v/index-entry tid id hash c-hash value)] diff --git a/modules/db/src/blaze/db/impl/search_param/token.clj b/modules/db/src/blaze/db/impl/search_param/token.clj index 988669f87..469030844 100644 --- a/modules/db/src/blaze/db/impl/search_param/token.clj +++ b/modules/db/src/blaze/db/impl/search_param/token.clj @@ -58,7 +58,7 @@ [_ code] ;; TODO: system (when-let [value (type/value code)] - [[nil (codec/v-hash value)]])) + [[nil (codec/v-hash value) true]])) (defn token-coding-entries [{:keys [code system]}] @@ -70,7 +70,7 @@ system (conj [nil (codec/v-hash (str system "|"))]) (and code system) - (conj [nil (codec/v-hash (str system "|" code))]) + (conj [nil (codec/v-hash (str system "|" code)) true]) (and code (nil? system)) (conj [nil (codec/v-hash (str "|" code))])))) diff --git a/modules/db/src/blaze/db/tx_log/local.clj b/modules/db/src/blaze/db/tx_log/local.clj index 1a0a28f44..787a39952 100644 --- a/modules/db/src/blaze/db/tx_log/local.clj +++ b/modules/db/src/blaze/db/tx_log/local.clj @@ -127,7 +127,7 @@ (let [key (Object.) queue (ArrayBlockingQueue. 10) queue-start (inc (:t (swap! state update :queues assoc key queue)))] - (log/trace "new-queue offset =" offset ", queue-start =" queue-start) + (log/trace "new-queue offset =" offset "queue-start =" queue-start) (->LocalQueue kv-store (volatile! offset) queue queue-start #(swap! state update :queues dissoc key))))) diff --git a/modules/db/test-perf/blaze/db/api_test_perf.clj b/modules/db/test-perf/blaze/db/api_test_perf.clj index c6653ed68..7bed864b9 100644 --- a/modules/db/test-perf/blaze/db/api_test_perf.clj +++ b/modules/db/test-perf/blaze/db/api_test_perf.clj @@ -11,8 +11,9 @@ [blaze.db.tx-log :as tx-log] [blaze.db.tx-log.local] [blaze.fhir.spec.type :as type] + [blaze.fhir.test-util :refer [structure-definition-repo]] [blaze.log] - [blaze.test-util :refer [structure-definition-repo with-system]] + [blaze.module.test-util :refer [with-system]] [clojure.test :refer [deftest]] [criterium.core :as criterium] [integrant.core :as ig] @@ -108,10 +109,10 @@ :method (type/codeable-concept {:text (type/string (str version))}) :code #fhir/CodeableConcept - {:coding - [#fhir/Coding - {:system #fhir/uri"system-191514" - :code #fhir/code"code-191518"}]}}])) + {:coding + [#fhir/Coding + {:system #fhir/uri"system-191514" + :code #fhir/code"code-191518"}]}}])) diff --git a/modules/db/test-perf/blaze/db/search_param_registry_test_perf.clj b/modules/db/test-perf/blaze/db/search_param_registry_test_perf.clj index ace7969fc..79b902d04 100644 --- a/modules/db/test-perf/blaze/db/search_param_registry_test_perf.clj +++ b/modules/db/test-perf/blaze/db/search_param_registry_test_perf.clj @@ -1,7 +1,8 @@ (ns blaze.db.search-param-registry-test-perf (:require [blaze.db.search-param-registry :as sr] - [blaze.test-util :refer [structure-definition-repo with-system]] + [blaze.fhir.test-util :refer [structure-definition-repo]] + [blaze.module.test-util :refer [with-system]] [clojure.test :refer [deftest testing]] [criterium.core :as criterium] [taoensso.timbre :as log])) diff --git a/modules/db/test/blaze/db/api_test.clj b/modules/db/test/blaze/db/api_test.clj index fdff82516..ef95872ea 100644 --- a/modules/db/test/blaze/db/api_test.clj +++ b/modules/db/test/blaze/db/api_test.clj @@ -23,8 +23,10 @@ [blaze.fhir.spec.generators :as fg] [blaze.fhir.spec.type :as type] [blaze.fhir.spec.type.system :as system] + [blaze.fhir.test-util :refer [given-failed-future]] [blaze.log] - [blaze.test-util :as tu :refer [given-failed-future satisfies-prop with-system]] + [blaze.module.test-util :refer [with-system]] + [blaze.test-util :as tu :refer [satisfies-prop]] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [are deftest is testing]] [clojure.test.check.generators :as gen] @@ -589,6 +591,27 @@ ::x ::y))))) +(deftest as-of-test + (with-system-data [{:blaze.db/keys [node]} config] + [[[:put {:fhir/type :fhir/Patient :id "0"}]] + [[:put {:fhir/type :fhir/Patient :id "1"}]]] + + (let [db (d/db node)] + + (testing "the newest t is 2" + (is (= 2 (d/basis-t db)))) + + (testing "the effective t of a DB as of 1 if 1" + (is (= 1 (d/t (d/as-of db 1)))))))) + + +(deftest t-test + (with-system-data [{:blaze.db/keys [node]} config] + [[[:put {:fhir/type :fhir/Patient :id "0"}]]] + + (is (= 1 (d/t (d/db node)))))) + + (deftest tx-test (with-system-data [{:blaze.db/keys [node]} config] [[[:put {:fhir/type :fhir/Patient :id "id-142136"}]]] @@ -3135,7 +3158,7 @@ [5 :id] := "id-5"))) (testing "type number" - (testing "decimal" + (testing "Decimal" (with-system-data [{:blaze.db/keys [node]} config] [[[:put {:fhir/type :fhir/RiskAssessment :id "id-0" @@ -3193,7 +3216,7 @@ count := 1 [0 :id] := "id-2"))))) - (testing "integer" + (testing "Integer" (with-system-data [{:blaze.db/keys [node]} config] [[[:put {:fhir/type :fhir/MolecularSequence :id "id-0" @@ -4159,7 +4182,7 @@ (testing "an unknown search-param errors" (doseq [target [node (d/db node)]] (given (d/compile-type-query target "Patient" [["foo" "bar"] - ["active" "true"]]) + ["active" "true"]]) ::anom/category := ::anom/not-found ::anom/message := "The search-param with code `foo` and type `Patient` was not found."))) @@ -4666,55 +4689,7 @@ node "Patient" "0" "Condition" [["code" "system|code-a"]]) count := 1 - [0 :id] := "1")) - - (testing "with code only" - (given @(pull-compartment-query - node "Patient" "0" "Condition" - [["code" "code-b"]]) - count := 1 - [0 :id] := "2")) - - (testing "with system|" - (given @(pull-compartment-query - node "Patient" "0" "Condition" - [["code" "system|"]]) - count := 2 - [0 :id] := "1" - [1 :id] := "2")))) - - (testing "quantity search parameter" - (testing "as first clause" - (testing "with [number]|[system]|[code]" - (given @(pull-compartment-query - node "Patient" "0" "Observation" - [["value-quantity" "42|http://unitsofmeasure.org|kg/m2"]]) - count := 1 - [0 :id] := "3")) - - (testing "with [number]|[code]" - (given @(pull-compartment-query - node "Patient" "0" "Observation" - [["value-quantity" "23|kg/m2"]]) - count := 1 - [0 :id] := "4"))) - - (testing "as second clause" - (testing "with [number]|[system]|[code]" - (given @(pull-compartment-query - node "Patient" "0" "Observation" - [["code" "system|"] - ["value-quantity" "42|http://unitsofmeasure.org|kg/m2"]]) - count := 1 - [0 :id] := "3")) - - (testing "with [number]|[code]" - (given @(pull-compartment-query - node "Patient" "0" "Observation" - [["code" "system|"] - ["value-quantity" "23|kg/m2"]]) - count := 1 - [0 :id] := "4"))))))) + [0 :id] := "1"))))))) (deftest compile-compartment-query-test diff --git a/modules/db/test/blaze/db/cache_collector_test.clj b/modules/db/test/blaze/db/cache_collector_test.clj index a62410340..8b0f7d826 100644 --- a/modules/db/test/blaze/db/cache_collector_test.clj +++ b/modules/db/test/blaze/db/cache_collector_test.clj @@ -2,7 +2,8 @@ (:require [blaze.db.cache-collector] [blaze.metrics.core :as metrics] - [blaze.test-util :as tu :refer [given-thrown with-system]] + [blaze.module.test-util :refer [with-system]] + [blaze.test-util :as tu :refer [given-thrown]] [clojure.spec.alpha :as s] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [deftest testing]] diff --git a/modules/db/test/blaze/db/impl/codec_test.clj b/modules/db/test/blaze/db/impl/codec_test.clj index 3d614c489..476f2f094 100644 --- a/modules/db/test/blaze/db/impl/codec_test.clj +++ b/modules/db/test/blaze/db/impl/codec_test.clj @@ -66,7 +66,7 @@ (prop/for-all [i (s/gen int?)] (= i (codec/decode-number (codec/number i)))))) - (testing "long" + (testing "Long" (are [n hex] (= hex (bs/hex (codec/number n))) Long/MIN_VALUE "3F8000000000000000" (inc Long/MIN_VALUE) "3F8000000000000001" @@ -125,7 +125,7 @@ 576460752303423489 "C00800000000000001" Long/MAX_VALUE "C07FFFFFFFFFFFFFFF")) - (testing "integer" + (testing "Integer" (are [n hex] (= hex (bs/hex (codec/number n))) Integer/MIN_VALUE "5F80000000" (int -1) "7F" diff --git a/modules/db/test/blaze/db/impl/index/resource_as_of_test_util.clj b/modules/db/test/blaze/db/impl/index/resource_as_of_test_util.clj index 3afb8681e..cb671bb21 100644 --- a/modules/db/test/blaze/db/impl/index/resource_as_of_test_util.clj +++ b/modules/db/test/blaze/db/impl/index/resource_as_of_test_util.clj @@ -2,9 +2,7 @@ (:require [blaze.byte-buffer :as bb] [blaze.byte-string :as bs] - [blaze.db.impl.codec :as codec] - [blaze.db.impl.index.resource-handle :as rh] - [blaze.fhir.hash :as hash])) + [blaze.db.impl.codec :as codec])) (set! *unchecked-math* :warn-on-boxed) @@ -17,12 +15,3 @@ {:type (codec/tid->type tid) :id (codec/id-string (bs/from-byte-buffer! buf id-size)) :t (codec/descending-long (bb/get-long! buf))})) - - -(defn decode-val [byte-array] - (let [buf (bb/wrap byte-array) - hash (hash/from-byte-buffer! buf) - state (bb/get-long! buf)] - {:hash hash - :num-changes (rh/state->num-changes state) - :op (rh/state->op state)})) diff --git a/modules/db/test/blaze/db/impl/index/resource_handle_test.clj b/modules/db/test/blaze/db/impl/index/resource_handle_test.clj index 931785444..15b1207b3 100644 --- a/modules/db/test/blaze/db/impl/index/resource_handle_test.clj +++ b/modules/db/test/blaze/db/impl/index/resource_handle_test.clj @@ -103,3 +103,12 @@ (let [rh-1 (resource-handle tid id t) rh-2 (resource-handle tid id t)] (= rh-1 rh-2)))))) + + +(deftest to-string-test + (satisfies-prop 100 + (prop/for-all [id (s/gen :blaze.resource/id) + t (s/gen :blaze.db/t)] + + (= (format "Condition[id = %s, t = %d]" id t) + (str (resource-handle 1495153489 id t)))))) diff --git a/modules/db/test/blaze/db/impl/index/rts_as_of_spec.clj b/modules/db/test/blaze/db/impl/index/rts_as_of_spec.clj index 3ec8174a5..867c6e510 100644 --- a/modules/db/test/blaze/db/impl/index/rts_as_of_spec.clj +++ b/modules/db/test/blaze/db/impl/index/rts_as_of_spec.clj @@ -16,4 +16,4 @@ :hash :blaze.resource/hash :num-changes nat-int? :op keyword?) - :ret bytes?) + :ret (s/coll-of :blaze.db.kv/put-entry-w-cf)) diff --git a/modules/db/test/blaze/db/impl/index/rts_as_of_test_util.clj b/modules/db/test/blaze/db/impl/index/rts_as_of_test_util.clj new file mode 100644 index 000000000..907331860 --- /dev/null +++ b/modules/db/test/blaze/db/impl/index/rts_as_of_test_util.clj @@ -0,0 +1,17 @@ +(ns blaze.db.impl.index.rts-as-of-test-util + (:require + [blaze.byte-buffer :as bb] + [blaze.db.impl.index.resource-handle :as rh] + [blaze.fhir.hash :as hash])) + + +(set! *unchecked-math* :warn-on-boxed) + + +(defn decode-val [byte-array] + (let [buf (bb/wrap byte-array) + hash (hash/from-byte-buffer! buf) + state (bb/get-long! buf)] + {:hash hash + :num-changes (rh/state->num-changes state) + :op (rh/state->op state)})) diff --git a/modules/db/test/blaze/db/impl/index/system_as_of_test_util.clj b/modules/db/test/blaze/db/impl/index/system_as_of_test_util.clj index fd8db7ce8..53151b7bf 100644 --- a/modules/db/test/blaze/db/impl/index/system_as_of_test_util.clj +++ b/modules/db/test/blaze/db/impl/index/system_as_of_test_util.clj @@ -2,9 +2,7 @@ (:require [blaze.byte-buffer :as bb] [blaze.byte-string :as bs] - [blaze.db.impl.codec :as codec] - [blaze.db.impl.index.resource-handle :as rh] - [blaze.fhir.hash :as hash])) + [blaze.db.impl.codec :as codec])) (set! *unchecked-math* :warn-on-boxed) @@ -15,12 +13,3 @@ {:t (codec/descending-long (bb/get-long! buf)) :type (codec/tid->type (bb/get-int! buf)) :id (codec/id-string (bs/from-byte-buffer! buf (bb/remaining buf)))})) - - -(defn decode-val [byte-array] - (let [buf (bb/wrap byte-array) - hash (hash/from-byte-buffer! buf) - state (bb/get-long! buf)] - {:hash hash - :num-changes (rh/state->num-changes state) - :op (rh/state->op state)})) diff --git a/modules/db/test/blaze/db/impl/index/t_by_instant_test.clj b/modules/db/test/blaze/db/impl/index/t_by_instant_test.clj index e37612bcb..83a967afa 100644 --- a/modules/db/test/blaze/db/impl/index/t_by_instant_test.clj +++ b/modules/db/test/blaze/db/impl/index/t_by_instant_test.clj @@ -4,7 +4,8 @@ [blaze.db.kv :as kv] [blaze.db.kv.mem] [blaze.db.kv.mem-spec] - [blaze.test-util :as tu :refer [with-system]] + [blaze.module.test-util :refer [with-system]] + [blaze.test-util :as tu] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [deftest is testing]]) (:import diff --git a/modules/db/test/blaze/db/impl/index/tx_error_test.clj b/modules/db/test/blaze/db/impl/index/tx_error_test.clj index 7dbd7b679..49c48a05b 100644 --- a/modules/db/test/blaze/db/impl/index/tx_error_test.clj +++ b/modules/db/test/blaze/db/impl/index/tx_error_test.clj @@ -5,7 +5,8 @@ [blaze.db.kv :as kv] [blaze.db.kv.mem] [blaze.db.kv.mem-spec] - [blaze.test-util :as tu :refer [with-system]] + [blaze.module.test-util :refer [with-system]] + [blaze.test-util :as tu] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [deftest is testing]] [cognitect.anomalies :as anom] diff --git a/modules/db/test/blaze/db/impl/index/tx_success_test.clj b/modules/db/test/blaze/db/impl/index/tx_success_test.clj index 7447efb18..7de029568 100644 --- a/modules/db/test/blaze/db/impl/index/tx_success_test.clj +++ b/modules/db/test/blaze/db/impl/index/tx_success_test.clj @@ -6,7 +6,8 @@ [blaze.db.kv.mem] [blaze.db.kv.mem-spec] [blaze.db.tx-cache] - [blaze.test-util :as tu :refer [with-system]] + [blaze.module.test-util :refer [with-system]] + [blaze.test-util :as tu] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [deftest is testing]] [integrant.core :as ig] diff --git a/modules/db/test/blaze/db/impl/index/type_as_of_test_util.clj b/modules/db/test/blaze/db/impl/index/type_as_of_test_util.clj index bd8e7f89f..c8e6db49f 100644 --- a/modules/db/test/blaze/db/impl/index/type_as_of_test_util.clj +++ b/modules/db/test/blaze/db/impl/index/type_as_of_test_util.clj @@ -2,9 +2,7 @@ (:require [blaze.byte-buffer :as bb] [blaze.byte-string :as bs] - [blaze.db.impl.codec :as codec] - [blaze.db.impl.index.resource-handle :as rh] - [blaze.fhir.hash :as hash])) + [blaze.db.impl.codec :as codec])) (set! *unchecked-math* :warn-on-boxed) @@ -15,12 +13,3 @@ {:type (codec/tid->type (bb/get-int! buf)) :t (codec/descending-long (bb/get-long! buf)) :id (codec/id-string (bs/from-byte-buffer! buf (bb/remaining buf)))})) - - -(defn decode-val [byte-array] - (let [buf (bb/wrap byte-array) - hash (hash/from-byte-buffer! buf) - state (bb/get-long! buf)] - {:hash hash - :num-changes (rh/state->num-changes state) - :op (rh/state->op state)})) diff --git a/modules/db/test/blaze/db/impl/iterators_test.clj b/modules/db/test/blaze/db/impl/iterators_test.clj index 36865491a..c0d8b6e69 100644 --- a/modules/db/test/blaze/db/impl/iterators_test.clj +++ b/modules/db/test/blaze/db/impl/iterators_test.clj @@ -7,7 +7,8 @@ [blaze.db.kv :as kv] [blaze.db.kv.mem] [blaze.db.kv.mem-spec] - [blaze.test-util :as tu :refer [with-system]] + [blaze.module.test-util :refer [with-system]] + [blaze.test-util :as tu] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [deftest is testing]])) diff --git a/modules/db/test/blaze/db/impl/search_param/composite_test.clj b/modules/db/test/blaze/db/impl/search_param/composite_test.clj index 75a6cef2a..53a7a9f23 100644 --- a/modules/db/test/blaze/db/impl/search_param/composite_test.clj +++ b/modules/db/test/blaze/db/impl/search_param/composite_test.clj @@ -15,7 +15,9 @@ [blaze.fhir.hash :as hash] [blaze.fhir.hash-spec] [blaze.fhir.spec.type] - [blaze.test-util :as tu :refer [structure-definition-repo with-system]] + [blaze.fhir.test-util :refer [structure-definition-repo]] + [blaze.module.test-util :refer [with-system]] + [blaze.test-util :as tu] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [are deftest testing]] [cognitect.anomalies :as anom] @@ -135,15 +137,15 @@ :status #fhir/code"final" :code #fhir/CodeableConcept - {:coding - [#fhir/Coding - {:system #fhir/uri"http://loinc.org" - :code #fhir/code"8480-6"}]} + {:coding + [#fhir/Coding + {:system #fhir/uri"http://loinc.org" + :code #fhir/code"8480-6"}]} :value #fhir/Quantity - {:value 100M - :code #fhir/code"mm[Hg]" - :system #fhir/uri"http://unitsofmeasure.org"}} + {:value 100M + :code #fhir/code"mm[Hg]" + :system #fhir/uri"http://unitsofmeasure.org"}} hash (hash/generate observation) [[_ k0] [_ k1] [_ k2] [_ k3] [_ k4] [_ k5] [_ k6] [_ k7] [_ k8] [_ k9] [_ k10] [_ k11] @@ -296,10 +298,10 @@ [value] (instance? GetChildrenExpression expr) [#fhir/CodeableConcept - {:coding - [#fhir/Coding - {:system #fhir/uri"system-204435" - :code #fhir/code"code-204441"}]}] + {:coding + [#fhir/Coding + {:system #fhir/uri"system-204435" + :code #fhir/code"code-204441"}]}] :else {::anom/category ::anom/fault ::x ::y}))] diff --git a/modules/db/test/blaze/db/impl/search_param/date_test.clj b/modules/db/test/blaze/db/impl/search_param/date_test.clj index 95d627750..982d67f65 100644 --- a/modules/db/test/blaze/db/impl/search_param/date_test.clj +++ b/modules/db/test/blaze/db/impl/search_param/date_test.clj @@ -14,7 +14,9 @@ [blaze.fhir-path :as fhir-path] [blaze.fhir.hash :as hash] [blaze.fhir.hash-spec] - [blaze.test-util :as tu :refer [structure-definition-repo with-system]] + [blaze.fhir.test-util :refer [structure-definition-repo]] + [blaze.module.test-util :refer [with-system]] + [blaze.test-util :as tu] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [deftest is testing]] [cognitect.anomalies :as anom] diff --git a/modules/db/test/blaze/db/impl/search_param/list_test.clj b/modules/db/test/blaze/db/impl/search_param/list_test.clj index e8f283e62..369e9ca2e 100644 --- a/modules/db/test/blaze/db/impl/search_param/list_test.clj +++ b/modules/db/test/blaze/db/impl/search_param/list_test.clj @@ -3,7 +3,9 @@ [blaze.byte-string-spec] [blaze.db.impl.search-param-spec] [blaze.db.search-param-registry :as sr] - [blaze.test-util :as tu :refer [structure-definition-repo with-system]] + [blaze.fhir.test-util :refer [structure-definition-repo]] + [blaze.module.test-util :refer [with-system]] + [blaze.test-util :as tu] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [deftest]] [juxt.iota :refer [given]] diff --git a/modules/db/test/blaze/db/impl/search_param/number_test.clj b/modules/db/test/blaze/db/impl/search_param/number_test.clj index 539ed40e8..87cd8fd42 100644 --- a/modules/db/test/blaze/db/impl/search_param/number_test.clj +++ b/modules/db/test/blaze/db/impl/search_param/number_test.clj @@ -14,7 +14,9 @@ [blaze.fhir.hash :as hash] [blaze.fhir.hash-spec] [blaze.fhir.spec.type] - [blaze.test-util :as tu :refer [structure-definition-repo with-system]] + [blaze.fhir.test-util :refer [structure-definition-repo]] + [blaze.module.test-util :refer [with-system]] + [blaze.test-util :as tu] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [are deftest is testing]] [cognitect.anomalies :as anom] diff --git a/modules/db/test/blaze/db/impl/search_param/quantity_test.clj b/modules/db/test/blaze/db/impl/search_param/quantity_test.clj index 15dafe2fb..7c4ae6a8d 100644 --- a/modules/db/test/blaze/db/impl/search_param/quantity_test.clj +++ b/modules/db/test/blaze/db/impl/search_param/quantity_test.clj @@ -14,7 +14,9 @@ [blaze.fhir.hash :as hash] [blaze.fhir.hash-spec] [blaze.fhir.spec.type] - [blaze.test-util :as tu :refer [structure-definition-repo with-system]] + [blaze.fhir.test-util :refer [structure-definition-repo]] + [blaze.module.test-util :refer [with-system]] + [blaze.test-util :as tu] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [are deftest is testing]] [cognitect.anomalies :as anom] diff --git a/modules/db/test/blaze/db/impl/search_param/string_test.clj b/modules/db/test/blaze/db/impl/search_param/string_test.clj index 94207ddd6..97c194490 100644 --- a/modules/db/test/blaze/db/impl/search_param/string_test.clj +++ b/modules/db/test/blaze/db/impl/search_param/string_test.clj @@ -14,7 +14,9 @@ [blaze.fhir-path :as fhir-path] [blaze.fhir.hash :as hash] [blaze.fhir.hash-spec] - [blaze.test-util :as tu :refer [structure-definition-repo with-system]] + [blaze.fhir.test-util :refer [structure-definition-repo]] + [blaze.module.test-util :refer [with-system]] + [blaze.test-util :as tu] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [deftest is testing]] [cognitect.anomalies :as anom] diff --git a/modules/db/test/blaze/db/impl/search_param/token_test.clj b/modules/db/test/blaze/db/impl/search_param/token_test.clj index 4f89cf757..f0829cb4b 100644 --- a/modules/db/test/blaze/db/impl/search_param/token_test.clj +++ b/modules/db/test/blaze/db/impl/search_param/token_test.clj @@ -13,8 +13,10 @@ [blaze.fhir-path :as fhir-path] [blaze.fhir.hash :as hash] [blaze.fhir.hash-spec] - [blaze.fhir.spec.type] - [blaze.test-util :as tu :refer [structure-definition-repo with-system]] + [blaze.fhir.spec.type :as type] + [blaze.fhir.test-util :refer [structure-definition-repo]] + [blaze.module.test-util :refer [with-system]] + [blaze.test-util :as tu] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [deftest is testing]] [cognitect.anomalies :as anom] @@ -213,6 +215,42 @@ :code := "code" :v-hash := (codec/v-hash "system-171339|"))))) + (testing "Patient active" + (doseq [active [#fhir/boolean true #fhir/boolean false]] + (let [patient + {:fhir/type :fhir/Patient :id "id-122929" + :active active} + hash (hash/generate patient) + [[_ k0] [_ k1]] + (search-param/index-entries + (sr/get search-param-registry "active" "Patient") + [] hash patient)] + + (testing "first SearchParamValueResource key is about `value`" + (given (sp-vr-tu/decode-key-human (bb/wrap k0)) + :code := "active" + :type := "Patient" + :v-hash := (codec/v-hash (str (type/value active))) + :id := "id-122929" + :hash-prefix := (hash/prefix hash))) + + (testing "first ResourceSearchParamValue key is about `value`" + (given (r-sp-v-tu/decode-key-human (bb/wrap k1)) + :type := "Patient" + :id := "id-122929" + :hash-prefix := (hash/prefix hash) + :code := "active" + :v-hash := (codec/v-hash (str (type/value active))))))) + + (testing "boolean without values doesn't produce index entries" + (let [patient + {:fhir/type :fhir/Patient :id "id-122929" + :active #fhir/boolean{:id "foo"}} + hash (hash/generate patient)] + (is (empty? (search-param/index-entries + (sr/get search-param-registry "active" "Patient") + [] hash patient)))))) + (testing "Patient identifier" (let [patient {:fhir/type :fhir/Patient :id "id-122929" diff --git a/modules/db/test/blaze/db/impl/search_param_test.clj b/modules/db/test/blaze/db/impl/search_param_test.clj index 70cbed90b..d450b5658 100644 --- a/modules/db/test/blaze/db/impl/search_param_test.clj +++ b/modules/db/test/blaze/db/impl/search_param_test.clj @@ -12,7 +12,9 @@ [blaze.fhir.hash :as hash] [blaze.fhir.hash-spec] [blaze.fhir.spec.type] - [blaze.test-util :as tu :refer [structure-definition-repo with-system]] + [blaze.fhir.test-util :refer [structure-definition-repo]] + [blaze.module.test-util :refer [with-system]] + [blaze.test-util :as tu] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [are deftest is testing]] [juxt.iota :refer [given]])) diff --git a/modules/db/test/blaze/db/node/resource_indexer_test.clj b/modules/db/test/blaze/db/node/resource_indexer_test.clj index d94ec328f..a5a56b0fa 100644 --- a/modules/db/test/blaze/db/node/resource_indexer_test.clj +++ b/modules/db/test/blaze/db/node/resource_indexer_test.clj @@ -24,8 +24,10 @@ [blaze.fhir.hash :as hash] [blaze.fhir.hash-spec] [blaze.fhir.spec.type] + [blaze.fhir.test-util :refer [given-failed-future structure-definition-repo]] [blaze.metrics.spec] - [blaze.test-util :as tu :refer [given-failed-future given-thrown structure-definition-repo with-system]] + [blaze.module.test-util :refer [with-system]] + [blaze.test-util :as tu :refer [given-thrown]] [clojure.spec.alpha :as s] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [deftest is testing]] @@ -200,6 +202,52 @@ (is (empty? (sp-vr-tu/decode-index-entries kv-store :id)))))) +(deftest index-patient-resource-test + (with-system [{kv-store [::kv/mem :blaze.db/index-kv-store] + resource-store ::rs/kv + :blaze.db.node/keys [resource-indexer]} config] + (let [resource + {:fhir/type :fhir/Patient :id "id-104313" + :active #fhir/boolean true} + hash (hash/generate resource)] + @(rs/put! resource-store {hash resource}) + @(resource-indexer/index-resources + resource-indexer + {:t 0 + :instant Instant/EPOCH + :tx-cmds + [{:op "put" + :type "Patient" + :id "id-104313" + :hash hash}]}) + + (testing "SearchParamValueResource index" + (is (every? #{["Patient" "id-104313" #blaze/hash-prefix"45142904"]} + (sp-vr-tu/decode-index-entries + kv-store :type :id :hash-prefix))) + (is (= (sp-vr-tu/decode-index-entries kv-store :code :v-hash) + [["active" (codec/v-hash "true")] + ["deceased" (codec/v-hash "false")] + ["_id" (codec/v-hash "id-104313")] + ["_lastUpdated" #blaze/byte-string"80008001"]]))) + + (testing "ResourceSearchParamValue index" + (is (every? #{["Patient" "id-104313" #blaze/hash-prefix"45142904"]} + (r-sp-v-tu/decode-index-entries + kv-store :type :id :hash-prefix))) + (is (= (r-sp-v-tu/decode-index-entries kv-store :code :v-hash) + [["active" (codec/v-hash "true")] + ["deceased" (codec/v-hash "false")] + ["_id" (codec/v-hash "id-104313")] + ["_lastUpdated" #blaze/byte-string"80008001"]]))) + + (testing "CompartmentResource index" + (is (empty? (cr-tu/decode-index-entries kv-store)))) + + (testing "CompartmentSearchParamValueResource index" + (is (empty? (c-sp-vr-tu/decode-index-entries kv-store))))))) + + (deftest index-condition-resource-test (with-system [{kv-store [::kv/mem :blaze.db/index-kv-store] resource-store ::rs/kv @@ -288,23 +336,7 @@ (c-sp-vr-tu/decode-index-entries kv-store :compartment :type :id :hash-prefix))) (is (= (c-sp-vr-tu/decode-index-entries kv-store :code :v-hash) - [["patient" (codec/v-hash "Patient/id-145552")] - ["patient" (codec/tid-id - (codec/tid "Patient") - (codec/id-byte-string "id-145552"))] - ["patient" (codec/v-hash "id-145552")] - ["code" (codec/v-hash "code-204441")] - ["code" (codec/v-hash "system-204435|")] - ["code" (codec/v-hash "system-204435|code-204441")] - ["onset-date" (codec-date/encode-range #system/date-time"2020-01-30")] - ["subject" (codec/v-hash "Patient/id-145552")] - ["subject" (codec/tid-id - (codec/tid "Patient") - (codec/id-byte-string "id-145552"))] - ["subject" (codec/v-hash "id-145552")] - ["_profile" (codec/v-hash "url-164445")] - ["_id" (codec/v-hash "id-204446")] - ["_lastUpdated" #blaze/byte-string"80008001"]])))))) + [["code" (codec/v-hash "system-204435|code-204441")]])))))) (deftest index-observation-resource-test @@ -424,7 +456,22 @@ ["subject" (codec/v-hash "Patient/id-180857")] ["status" (codec/v-hash "status-193613")] ["_id" (codec/v-hash "id-192702")] - ["_lastUpdated" #blaze/byte-string"80008001"]])))))) + ["_lastUpdated" #blaze/byte-string"80008001"]]))) + + (testing "CompartmentResource index" + (is (= (cr-tu/decode-index-entries kv-store :compartment :type :id) + [[["Patient" "id-180857"] "Observation" "id-192702"]]))) + + (testing "CompartmentSearchParamValueResource index" + (is (every? #{[["Patient" "id-180857"] "Observation" "id-192702" + #blaze/hash-prefix"651D1F37"]} + (c-sp-vr-tu/decode-index-entries + kv-store :compartment :type :id :hash-prefix))) + (is (= (c-sp-vr-tu/decode-index-entries kv-store :code :v-hash) + [["category" (codec/v-hash "system-193558|code-193603")] + ["code" (codec/v-hash "system-193821|code-193824")] + ["combo-code" (codec/v-hash "system-193821|code-193824")] + ["status" (codec/v-hash "status-193613")]])))))) (deftest index-delete-cmd-test diff --git a/modules/db/test/blaze/db/node/tx_indexer/verify_test.clj b/modules/db/test/blaze/db/node/tx_indexer/verify_test.clj index c0302f929..7bb1bc8a8 100644 --- a/modules/db/test/blaze/db/node/tx_indexer/verify_test.clj +++ b/modules/db/test/blaze/db/node/tx_indexer/verify_test.clj @@ -3,6 +3,7 @@ [blaze.db.api :as d] [blaze.db.impl.codec :as codec] [blaze.db.impl.index.resource-as-of-test-util :as rao-tu] + [blaze.db.impl.index.rts-as-of-test-util :as rts-tu] [blaze.db.impl.index.system-as-of-test-util :as sao-tu] [blaze.db.impl.index.system-stats-test-util :as ss-tu] [blaze.db.impl.index.type-as-of-test-util :as tao-tu] @@ -20,7 +21,8 @@ [blaze.fhir.hash-spec] [blaze.fhir.spec.type] [blaze.log] - [blaze.test-util :as tu :refer [with-system]] + [blaze.module.test-util :refer [with-system]] + [blaze.test-util :as tu] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [deftest is testing]] [cognitect.anomalies :as anom] @@ -45,7 +47,7 @@ (deftest verify-tx-cmds-test - (testing "adding one patient to an empty store" + (testing "adding one Patient to an empty store" (let [hash (hash/generate patient-0)] (doseq [op [:create :put] if-none-match [nil "*"]] @@ -55,17 +57,20 @@ [(cond-> {:op (name op) :type "Patient" :id "0" :hash hash} if-none-match (assoc :if-none-match if-none-match))]) + + count := 5 + [0 0] := :resource-as-of-index [0 1 rao-tu/decode-key] := {:type "Patient" :id "0" :t 1} - [0 2 rao-tu/decode-val] := {:hash hash :num-changes 1 :op op} + [0 2 rts-tu/decode-val] := {:hash hash :num-changes 1 :op op} [1 0] := :type-as-of-index [1 1 tao-tu/decode-key] := {:type "Patient" :t 1 :id "0"} - [1 2 tao-tu/decode-val] := {:hash hash :num-changes 1 :op op} + [1 2 rts-tu/decode-val] := {:hash hash :num-changes 1 :op op} [2 0] := :system-as-of-index [2 1 sao-tu/decode-key] := {:t 1 :type "Patient" :id "0"} - [2 2 sao-tu/decode-val] := {:hash hash :num-changes 1 :op op} + [2 2 rts-tu/decode-val] := {:hash hash :num-changes 1 :op op} [3 0] := :type-stats-index [3 1 ts-tu/decode-key] := {:type "Patient" :t 1} @@ -86,17 +91,20 @@ [(cond-> {:op "put" :type "Patient" :id "0" :hash hash} if-match (assoc :if-match if-match))]) + + count := 5 + [0 0] := :resource-as-of-index [0 1 rao-tu/decode-key] := {:type "Patient" :id "0" :t 2} - [0 2 rao-tu/decode-val] := {:hash hash :num-changes 2 :op :put} + [0 2 rts-tu/decode-val] := {:hash hash :num-changes 2 :op :put} [1 0] := :type-as-of-index [1 1 tao-tu/decode-key] := {:type "Patient" :t 2 :id "0"} - [1 2 tao-tu/decode-val] := {:hash hash :num-changes 2 :op :put} + [1 2 rts-tu/decode-val] := {:hash hash :num-changes 2 :op :put} [2 0] := :system-as-of-index [2 1 sao-tu/decode-key] := {:t 2 :type "Patient" :id "0"} - [2 2 sao-tu/decode-val] := {:hash hash :num-changes 2 :op :put} + [2 2 rts-tu/decode-val] := {:hash hash :num-changes 2 :op :put} [3 0] := :type-stats-index [3 1 ts-tu/decode-key] := {:type "Patient" :t 2} @@ -106,7 +114,7 @@ [4 1 ss-tu/decode-key] := {:t 2} [4 2 ss-tu/decode-val] := {:total 1 :num-changes 2}))))) - (testing "adding a second version of an already deleted patient" + (testing "adding a second version of an already deleted Patient" (let [hash (hash/generate patient-0-v2)] (doseq [if-match [nil 2 [2] [1 2]]] (with-system-data [{:blaze.db/keys [node]} config] @@ -118,17 +126,20 @@ [(cond-> {:op "put" :type "Patient" :id "0" :hash hash} if-match (assoc :if-match if-match))]) + + count := 5 + [0 0] := :resource-as-of-index [0 1 rao-tu/decode-key] := {:type "Patient" :id "0" :t 3} - [0 2 rao-tu/decode-val] := {:hash hash :num-changes 3 :op :put} + [0 2 rts-tu/decode-val] := {:hash hash :num-changes 3 :op :put} [1 0] := :type-as-of-index [1 1 tao-tu/decode-key] := {:type "Patient" :t 3 :id "0"} - [1 2 tao-tu/decode-val] := {:hash hash :num-changes 3 :op :put} + [1 2 rts-tu/decode-val] := {:hash hash :num-changes 3 :op :put} [2 0] := :system-as-of-index [2 1 sao-tu/decode-key] := {:t 3 :type "Patient" :id "0"} - [2 2 sao-tu/decode-val] := {:hash hash :num-changes 3 :op :put} + [2 2 rts-tu/decode-val] := {:hash hash :num-changes 3 :op :put} [3 0] := :type-stats-index [3 1 ts-tu/decode-key] := {:type "Patient" :t 3} @@ -138,7 +149,7 @@ [4 1 ss-tu/decode-key] := {:t 3} [4 2 ss-tu/decode-val] := {:total 1 :num-changes 3}))))) - (testing "adding a patient with identical content" + (testing "adding a Patient with identical content" (with-system-data [{:blaze.db/keys [node]} config] [[[:put patient-0]]] @@ -147,7 +158,7 @@ [{:op "put" :type "Patient" :id "0" :hash (hash/generate patient-0)}]))))) - (testing "keeping a non-existing patient fails" + (testing "keeping a non-existing Patient fails" (with-system [{:blaze.db/keys [node]} config] (let [tx-cmd {:op "keep" :type "Patient" :id "0" :hash (hash/generate patient-0)}] @@ -156,7 +167,7 @@ ::anom/message := "Keep failed on `Patient/0`." :blaze.db/tx-cmd := tx-cmd)))) - (testing "keeping a non-matching patient fails" + (testing "keeping a non-matching Patient fails" (with-system-data [{:blaze.db/keys [node]} config] [[[:put patient-0]] [[:put patient-0-v2]]] @@ -167,7 +178,7 @@ ::anom/message := "Keep failed on `Patient/0`." :blaze.db/tx-cmd := tx-cmd)))) - (testing "keeping a hash matching but non-matching if-match patient fails" + (testing "keeping a hash matching but non-matching if-match Patient fails" (with-system-data [{:blaze.db/keys [node]} config] [[[:put patient-0]] [[:put patient-0-v2]]] @@ -201,7 +212,7 @@ :http/status := 412 :blaze.db/tx-cmd := tx-cmd)))))) - (testing "keeping a matching patient" + (testing "keeping a matching Patient" (with-system-data [{:blaze.db/keys [node]} config] [[[:put patient-0]]] @@ -215,22 +226,25 @@ if-match (assoc :if-match if-match))]))))))) - (testing "deleting a patient from an empty store" + (testing "deleting a Patient from an empty store" (with-system [{:blaze.db/keys [node]} config] (given (verify/verify-tx-cmds (d/db node) 1 [{:op "delete" :type "Patient" :id "0"}]) + + count := 5 + [0 0] := :resource-as-of-index [0 1 rao-tu/decode-key] := {:type "Patient" :id "0" :t 1} - [0 2 rao-tu/decode-val] := {:hash hash/deleted-hash :num-changes 1 :op :delete} + [0 2 rts-tu/decode-val] := {:hash hash/deleted-hash :num-changes 1 :op :delete} [1 0] := :type-as-of-index [1 1 tao-tu/decode-key] := {:type "Patient" :t 1 :id "0"} - [1 2 tao-tu/decode-val] := {:hash hash/deleted-hash :num-changes 1 :op :delete} + [1 2 rts-tu/decode-val] := {:hash hash/deleted-hash :num-changes 1 :op :delete} [2 0] := :system-as-of-index [2 1 sao-tu/decode-key] := {:t 1 :type "Patient" :id "0"} - [2 2 sao-tu/decode-val] := {:hash hash/deleted-hash :num-changes 1 :op :delete} + [2 2 rts-tu/decode-val] := {:hash hash/deleted-hash :num-changes 1 :op :delete} [3 0] := :type-stats-index [3 1 ts-tu/decode-key] := {:type "Patient" :t 1} @@ -240,24 +254,27 @@ [4 1 ss-tu/decode-key] := {:t 1} [4 2 ss-tu/decode-val] := {:total 0 :num-changes 1}))) - (testing "deleting an already deleted patient" + (testing "deleting an already deleted Patient" (with-system-data [{:blaze.db/keys [node]} config] [[[:delete "Patient" "0"]]] (given (verify/verify-tx-cmds (d/db node) 2 [{:op "delete" :type "Patient" :id "0"}]) + + count := 5 + [0 0] := :resource-as-of-index [0 1 rao-tu/decode-key] := {:type "Patient" :id "0" :t 2} - [0 2 rao-tu/decode-val] := {:hash hash/deleted-hash :num-changes 2 :op :delete} + [0 2 rts-tu/decode-val] := {:hash hash/deleted-hash :num-changes 2 :op :delete} [1 0] := :type-as-of-index [1 1 tao-tu/decode-key] := {:type "Patient" :t 2 :id "0"} - [1 2 tao-tu/decode-val] := {:hash hash/deleted-hash :num-changes 2 :op :delete} + [1 2 rts-tu/decode-val] := {:hash hash/deleted-hash :num-changes 2 :op :delete} [2 0] := :system-as-of-index [2 1 sao-tu/decode-key] := {:t 2 :type "Patient" :id "0"} - [2 2 sao-tu/decode-val] := {:hash hash/deleted-hash :num-changes 2 :op :delete} + [2 2 rts-tu/decode-val] := {:hash hash/deleted-hash :num-changes 2 :op :delete} [3 0] := :type-stats-index [3 1 ts-tu/decode-key] := {:type "Patient" :t 2} @@ -267,24 +284,27 @@ [4 1 ss-tu/decode-key] := {:t 2} [4 2 ss-tu/decode-val] := {:total 0 :num-changes 2}))) - (testing "deleting an existing patient" + (testing "deleting an existing Patient" (with-system-data [{:blaze.db/keys [node]} config] [[[:put patient-0]]] (given (verify/verify-tx-cmds (d/db node) 2 [{:op "delete" :type "Patient" :id "0"}]) + + count := 5 + [0 0] := :resource-as-of-index [0 1 rao-tu/decode-key] := {:type "Patient" :id "0" :t 2} - [0 2 rao-tu/decode-val] := {:hash hash/deleted-hash :num-changes 2 :op :delete} + [0 2 rts-tu/decode-val] := {:hash hash/deleted-hash :num-changes 2 :op :delete} [1 0] := :type-as-of-index [1 1 tao-tu/decode-key] := {:type "Patient" :t 2 :id "0"} - [1 2 tao-tu/decode-val] := {:hash hash/deleted-hash :num-changes 2 :op :delete} + [1 2 rts-tu/decode-val] := {:hash hash/deleted-hash :num-changes 2 :op :delete} [2 0] := :system-as-of-index [2 1 sao-tu/decode-key] := {:t 2 :type "Patient" :id "0"} - [2 2 sao-tu/decode-val] := {:hash hash/deleted-hash :num-changes 2 :op :delete} + [2 2 rts-tu/decode-val] := {:hash hash/deleted-hash :num-changes 2 :op :delete} [3 0] := :type-stats-index [3 1 ts-tu/decode-key] := {:type "Patient" :t 2} @@ -302,17 +322,20 @@ (given (verify/verify-tx-cmds (d/db node) 2 [{:op "put" :type "Patient" :id "1" :hash hash}]) + + count := 5 + [0 0] := :resource-as-of-index [0 1 rao-tu/decode-key] := {:type "Patient" :id "1" :t 2} - [0 2 rao-tu/decode-val] := {:hash hash :num-changes 1 :op :put} + [0 2 rts-tu/decode-val] := {:hash hash :num-changes 1 :op :put} [1 0] := :type-as-of-index [1 1 tao-tu/decode-key] := {:type "Patient" :t 2 :id "1"} - [1 2 tao-tu/decode-val] := {:hash hash :num-changes 1 :op :put} + [1 2 rts-tu/decode-val] := {:hash hash :num-changes 1 :op :put} [2 0] := :system-as-of-index [2 1 sao-tu/decode-key] := {:t 2 :type "Patient" :id "1"} - [2 2 sao-tu/decode-val] := {:hash hash :num-changes 1 :op :put} + [2 2 rts-tu/decode-val] := {:hash hash :num-changes 1 :op :put} [3 0] := :type-stats-index [3 1 ts-tu/decode-key] := {:type "Patient" :t 2} @@ -414,17 +437,20 @@ (given (verify/verify-tx-cmds (d/db node) 3 [{:op "put" :type "Patient" :id "0" :hash hash}]) + + count := 5 + [0 0] := :resource-as-of-index [0 1 rao-tu/decode-key] := {:type "Patient" :id "0" :t 3} - [0 2 rao-tu/decode-val] := {:hash hash :num-changes 3 :op :put} + [0 2 rts-tu/decode-val] := {:hash hash :num-changes 3 :op :put} [1 0] := :type-as-of-index [1 1 tao-tu/decode-key] := {:type "Patient" :t 3 :id "0"} - [1 2 tao-tu/decode-val] := {:hash hash :num-changes 3 :op :put} + [1 2 rts-tu/decode-val] := {:hash hash :num-changes 3 :op :put} [2 0] := :system-as-of-index [2 1 sao-tu/decode-key] := {:t 3 :type "Patient" :id "0"} - [2 2 sao-tu/decode-val] := {:hash hash :num-changes 3 :op :put} + [2 2 rts-tu/decode-val] := {:hash hash :num-changes 3 :op :put} [3 0] := :type-stats-index [3 1 ts-tu/decode-key] := {:type "Patient" :t 3} diff --git a/modules/db/test/blaze/db/node_test.clj b/modules/db/test/blaze/db/node_test.clj index b22b78b33..0ff5da515 100644 --- a/modules/db/test/blaze/db/node_test.clj +++ b/modules/db/test/blaze/db/node_test.clj @@ -24,9 +24,11 @@ [blaze.db.tx-log.local-spec] [blaze.db.tx-log.spec :refer [tx-log?]] [blaze.executors :as ex] + [blaze.fhir.test-util :refer [given-failed-future]] [blaze.log] [blaze.metrics.spec] - [blaze.test-util :as tu :refer [given-failed-future given-thrown with-system]] + [blaze.module.test-util :refer [with-system]] + [blaze.test-util :as tu :refer [given-thrown]] [clojure.spec.alpha :as s] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [deftest is testing]] diff --git a/modules/db/test/blaze/db/resource_cache_test.clj b/modules/db/test/blaze/db/resource_cache_test.clj index 29b16d645..821e9da6e 100644 --- a/modules/db/test/blaze/db/resource_cache_test.clj +++ b/modules/db/test/blaze/db/resource_cache_test.clj @@ -11,7 +11,8 @@ [blaze.db.resource-store.spec :refer [resource-store?]] [blaze.fhir.hash :as hash] [blaze.fhir.hash-spec] - [blaze.test-util :as tu :refer [given-thrown with-system]] + [blaze.module.test-util :refer [with-system]] + [blaze.test-util :as tu :refer [given-thrown]] [clojure.spec.alpha :as s] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [are deftest is testing]] diff --git a/modules/db/test/blaze/db/search_param_registry_test.clj b/modules/db/test/blaze/db/search_param_registry_test.clj index 8d966d1c6..59dfa68b6 100644 --- a/modules/db/test/blaze/db/search_param_registry_test.clj +++ b/modules/db/test/blaze/db/search_param_registry_test.clj @@ -5,7 +5,9 @@ [blaze.fhir-path :as fhir-path] [blaze.fhir.spec.type] [blaze.fhir.structure-definition-repo.spec :refer [structure-definition-repo?]] - [blaze.test-util :as tu :refer [given-thrown structure-definition-repo with-system]] + [blaze.fhir.test-util :refer [structure-definition-repo]] + [blaze.module.test-util :refer [with-system]] + [blaze.test-util :as tu :refer [given-thrown]] [clojure.spec.alpha :as s] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [deftest is testing]] diff --git a/modules/db/test/blaze/db/test_util.clj b/modules/db/test/blaze/db/test_util.clj index a91dc844a..ea7ca5516 100644 --- a/modules/db/test/blaze/db/test_util.clj +++ b/modules/db/test/blaze/db/test_util.clj @@ -9,7 +9,8 @@ [blaze.db.tx-cache] [blaze.db.tx-log :as tx-log] [blaze.db.tx-log.local] - [blaze.test-util :refer [structure-definition-repo with-system]] + [blaze.fhir.test-util :refer [structure-definition-repo]] + [blaze.module.test-util :refer [with-system]] [integrant.core :as ig] [java-time.api :as time])) diff --git a/modules/db/test/blaze/db/tx_cache_test.clj b/modules/db/test/blaze/db/tx_cache_test.clj index fcb0ffb71..908e10803 100644 --- a/modules/db/test/blaze/db/tx_cache_test.clj +++ b/modules/db/test/blaze/db/tx_cache_test.clj @@ -3,7 +3,8 @@ [blaze.db.kv :as kv] [blaze.db.kv.mem] [blaze.db.tx-cache] - [blaze.test-util :as tu :refer [given-thrown with-system]] + [blaze.module.test-util :refer [with-system]] + [blaze.test-util :as tu :refer [given-thrown]] [clojure.spec.alpha :as s] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [deftest is testing]] diff --git a/modules/db/test/blaze/db/tx_log/local_test.clj b/modules/db/test/blaze/db/tx_log/local_test.clj index f8276d6b3..2e01e7e22 100644 --- a/modules/db/test/blaze/db/tx_log/local_test.clj +++ b/modules/db/test/blaze/db/tx_log/local_test.clj @@ -1,5 +1,6 @@ (ns blaze.db.tx-log.local-test (:require + [blaze.async.comp :as ac] [blaze.byte-string :as bs] [blaze.db.kv :as kv] [blaze.db.kv.mem] @@ -11,8 +12,10 @@ [blaze.db.tx-log.spec] [blaze.fhir.hash :as hash] [blaze.fhir.hash-spec] + [blaze.fhir.test-util :refer [given-failed-future]] [blaze.log] - [blaze.test-util :as tu :refer [given-failed-future given-thrown with-system]] + [blaze.module.test-util :refer [with-system]] + [blaze.test-util :as tu :refer [given-thrown]] [clojure.spec.alpha :as s] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [deftest is testing]] @@ -299,3 +302,60 @@ (with-open [queue (tx-log/new-queue tx-log 1)] (is (empty? (tx-log/poll! queue (time/millis 10))))))))) + + +(deftest new-queue-test + (testing "it is possible to open two queues" + (testing "with one existing transaction" + (with-system [{tx-log ::tx-log/local} + (assoc-kv-store-init-data + config + [[(codec/encode-key 1) + (codec/encode-tx-data + (Instant/ofEpochSecond 0) + [{:op "create" :type "Patient" :id "0" + :hash patient-hash-0}])]])] + + (let [fn #(with-open [queue (tx-log/new-queue tx-log 0)] + (->> (fn [] (tx-log/poll! queue (time/millis 10))) + (repeatedly 10) + (flatten) + (first))) + tx-data-1 (ac/supply-async fn) + tx-data-2 (ac/supply-async fn)] + + (is (= @tx-data-1 @tx-data-2)) + + (given @tx-data-1 + :t := 1 + :instant := (Instant/ofEpochSecond 0) + [:tx-cmds 0 :op] := "create" + [:tx-cmds 0 :type] := "Patient" + [:tx-cmds 0 :id] := "0" + [:tx-cmds 0 :hash] := patient-hash-0)))) + + (testing "with one incoming incoming transaction" + (with-system [{tx-log ::tx-log/local} config] + + (let [fn #(with-open [queue (tx-log/new-queue tx-log 0)] + (->> (fn [] (tx-log/poll! queue (time/millis 10))) + (repeatedly 50) + (flatten) + (first))) + tx-data-1 (ac/supply-async fn) + tx-data-2 (ac/supply-async fn)] + + @(tx-log/submit + tx-log + [{:op "create" :type "Patient" :id "0" :hash patient-hash-0}] + nil) + + (is (= @tx-data-1 @tx-data-2)) + + (given @tx-data-1 + :t := 1 + :instant := (Instant/ofEpochSecond 0) + [:tx-cmds 0 :op] := "create" + [:tx-cmds 0 :type] := "Patient" + [:tx-cmds 0 :id] := "0" + [:tx-cmds 0 :hash] := patient-hash-0)))))) diff --git a/modules/executor/Makefile b/modules/executor/Makefile index 8eb60f27a..196a53ceb 100644 --- a/modules/executor/Makefile +++ b/modules/executor/Makefile @@ -1,16 +1,13 @@ lint: clj-kondo --lint src test deps.edn -prep: - clojure -X:deps prep - -test: prep +test: clojure -M:test:kaocha --profile :ci -test-coverage: prep +test-coverage: clojure -M:test:coverage clean: rm -rf .clj-kondo/.cache .cpcache target -.PHONY: lint prep test test-coverage clean +.PHONY: lint test test-coverage clean diff --git a/modules/executor/deps.edn b/modules/executor/deps.edn index f6af837aa..db07d212a 100644 --- a/modules/executor/deps.edn +++ b/modules/executor/deps.edn @@ -1,10 +1,4 @@ -{:deps - { - ;; TODO: only needed for prepping - blaze/fhir-structure - {:local/root "../fhir-structure"}} - - :aliases +{:aliases {:test {:extra-paths ["test"] diff --git a/modules/extern-terminology-service/.clj-kondo/config.edn b/modules/extern-terminology-service/.clj-kondo/config.edn index 2518b1eac..531a77907 100644 --- a/modules/extern-terminology-service/.clj-kondo/config.edn +++ b/modules/extern-terminology-service/.clj-kondo/config.edn @@ -1,5 +1,5 @@ {:lint-as - {blaze.test-util/with-system clojure.core/with-open + {blaze.module.test-util/with-system clojure.core/with-open prometheus.alpha/defcounter clojure.core/def prometheus.alpha/defhistogram clojure.core/def} diff --git a/modules/extern-terminology-service/deps.edn b/modules/extern-terminology-service/deps.edn index 0dd1cbdc5..59fe46706 100644 --- a/modules/extern-terminology-service/deps.edn +++ b/modules/extern-terminology-service/deps.edn @@ -13,8 +13,8 @@ {:extra-paths ["test"] :extra-deps - {blaze/test-util - {:local/root "../test-util"} + {blaze/fhir-test-util + {:local/root "../fhir-test-util"} com.pgs-soft/HttpClientMock {:mvn/version "1.0.0"}}} diff --git a/modules/extern-terminology-service/test/blaze/terminology_service/extern_test.clj b/modules/extern-terminology-service/test/blaze/terminology_service/extern_test.clj index 51bc1e374..3eb4af6da 100644 --- a/modules/extern-terminology-service/test/blaze/terminology_service/extern_test.clj +++ b/modules/extern-terminology-service/test/blaze/terminology_service/extern_test.clj @@ -1,8 +1,10 @@ (ns blaze.terminology-service.extern-test (:require + [blaze.fhir.test-util] + [blaze.module.test-util :refer [with-system]] [blaze.terminology-service :as ts] [blaze.terminology-service.extern] - [blaze.test-util :as tu :refer [given-thrown with-system]] + [blaze.test-util :as tu :refer [given-thrown]] [clojure.spec.alpha :as s] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [deftest testing]] diff --git a/modules/fhir-client/.clj-kondo/config.edn b/modules/fhir-client/.clj-kondo/config.edn index 935e82c01..d7758a294 100644 --- a/modules/fhir-client/.clj-kondo/config.edn +++ b/modules/fhir-client/.clj-kondo/config.edn @@ -15,6 +15,10 @@ {:level :warning} :warn-on-reflection - {:level :warning :warn-only-on-interop true}} + {:level :warning :warn-only-on-interop true} + + :consistent-alias + {:aliases + {cognitect.anomalies anom}}} :skip-comments true} diff --git a/modules/fhir-client/deps.edn b/modules/fhir-client/deps.edn index f5bf9c960..76c1e37bd 100644 --- a/modules/fhir-client/deps.edn +++ b/modules/fhir-client/deps.edn @@ -22,8 +22,8 @@ {:extra-paths ["test"] :extra-deps - {blaze/test-util - {:local/root "../test-util"} + {blaze/fhir-test-util + {:local/root "../fhir-test-util"} com.pgs-soft/HttpClientMock {:mvn/version "1.0.0"}}} diff --git a/modules/fhir-client/test/blaze/fhir_client_test.clj b/modules/fhir-client/test/blaze/fhir_client_test.clj index afaa35f12..400681174 100644 --- a/modules/fhir-client/test/blaze/fhir_client_test.clj +++ b/modules/fhir-client/test/blaze/fhir_client_test.clj @@ -3,7 +3,8 @@ [blaze.fhir-client :as fhir-client] [blaze.fhir-client-spec] [blaze.fhir.spec.type] - [blaze.test-util :as tu :refer [given-failed-future]] + [blaze.fhir.test-util :refer [given-failed-future]] + [blaze.test-util :as tu] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [deftest is testing]] [cognitect.anomalies :as anom] diff --git a/modules/fhir-path/.clj-kondo/config.edn b/modules/fhir-path/.clj-kondo/config.edn index e3b746ad7..97e80c930 100644 --- a/modules/fhir-path/.clj-kondo/config.edn +++ b/modules/fhir-path/.clj-kondo/config.edn @@ -12,6 +12,10 @@ {:level :warning} :warn-on-reflection - {:level :warning :warn-only-on-interop true}} + {:level :warning :warn-only-on-interop true} + + :consistent-alias + {:aliases + {cognitect.anomalies anom}}} :skip-comments true} diff --git a/modules/fhir-path/deps.edn b/modules/fhir-path/deps.edn index 24e850d9b..0d9a8dfd1 100644 --- a/modules/fhir-path/deps.edn +++ b/modules/fhir-path/deps.edn @@ -3,18 +3,15 @@ {:local/root "../fhir-structure"} info.cqframework/cql - {:mvn/version "2.10.0"}} + {:mvn/version "2.11.0"}} :aliases {:test {:extra-paths ["test"] :extra-deps - {blaze/test-util - {:local/root "../test-util"} - - org.clojars.akiel/iota - {:mvn/version "0.1"}}} + {blaze/fhir-test-util + {:local/root "../fhir-test-util"}}} :kaocha {:extra-deps diff --git a/modules/fhir-path/test/blaze/fhir_path_test.clj b/modules/fhir-path/test/blaze/fhir_path_test.clj index 502dcc8e9..56e12d701 100644 --- a/modules/fhir-path/test/blaze/fhir_path_test.clj +++ b/modules/fhir-path/test/blaze/fhir_path_test.clj @@ -6,6 +6,7 @@ [blaze.fhir-path-spec] [blaze.fhir.spec :as fhir-spec] [blaze.fhir.spec.type] + [blaze.fhir.test-util] [blaze.test-util :as tu] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [are deftest is testing]] diff --git a/modules/fhir-structure/.clj-kondo/config.edn b/modules/fhir-structure/.clj-kondo/config.edn index cf2b2e2cb..3bfbbaa91 100644 --- a/modules/fhir-structure/.clj-kondo/config.edn +++ b/modules/fhir-structure/.clj-kondo/config.edn @@ -1,7 +1,7 @@ {:lint-as {blaze.fhir.spec.type.macros/def-primitive-type clojure.core/deftype blaze.fhir.spec.type.macros/defextended clojure.core/defrecord - blaze.test-util/with-system clojure.core/with-open} + blaze.module.test-util/with-system clojure.core/with-open} :hooks {:macroexpand @@ -29,6 +29,16 @@ :warn-on-reflection {:level :warning :warn-only-on-interop true} + :consistent-alias + {:aliases + {blaze.anomaly ba + blaze.executors ex + cognitect.anomalies anom + clojure.spec.alpha s + clojure.string str + integrant.core ig + taoensso.timbre log}} + :unused-private-var {:exclude [blaze.fhir.spec.type/at-utc]}} diff --git a/modules/fhir-structure/deps.edn b/modules/fhir-structure/deps.edn index c8c77c515..2952940ba 100644 --- a/modules/fhir-structure/deps.edn +++ b/modules/fhir-structure/deps.edn @@ -14,7 +14,7 @@ {:local/root "../module-base"} com.github.ben-manes.caffeine/caffeine - {:mvn/version "3.1.6"} + {:mvn/version "3.1.8"} com.fasterxml.jackson.dataformat/jackson-dataformat-cbor {:mvn/version "2.15.2"} @@ -47,15 +47,15 @@ {:build {:deps {io.github.clojure/tools.build - {:git/tag "v0.9.4" :git/sha "76b78fe"}} + {:git/tag "v0.9.5" :git/sha "24f2894"}} :ns-default build} :test {:extra-paths ["test"] :extra-deps - {blaze/test-util - {:local/root "../test-util"}}} + {blaze/fhir-test-util + {:local/root "../fhir-test-util"}}} :kaocha {:extra-deps diff --git a/modules/fhir-structure/src/blaze/fhir/spec/type.clj b/modules/fhir-structure/src/blaze/fhir/spec/type.clj index 387815d85..d589600b4 100644 --- a/modules/fhir-structure/src/blaze/fhir/spec/type.clj +++ b/modules/fhir-structure/src/blaze/fhir/spec/type.clj @@ -39,7 +39,9 @@ (set! *unchecked-math* :warn-on-boxed) -(defn type [x] +(defn type + "Returns the FHIR type if `x` if it has some." + [x] (p/-type x)) diff --git a/modules/fhir-structure/test/blaze/fhir/spec/impl_test.clj b/modules/fhir-structure/test/blaze/fhir/spec/impl_test.clj index 76d630826..5502a8529 100644 --- a/modules/fhir-structure/test/blaze/fhir/spec/impl_test.clj +++ b/modules/fhir-structure/test/blaze/fhir/spec/impl_test.clj @@ -8,7 +8,8 @@ [blaze.fhir.spec.impl.xml-spec] [blaze.fhir.spec.type :as type] [blaze.fhir.structure-definition-repo :as sdr] - [blaze.test-util :as tu :refer [structure-definition-repo]] + [blaze.fhir.test-util :refer [structure-definition-repo]] + [blaze.test-util :as tu] [clojure.alpha.spec :as s2] [clojure.data.xml.name :as xml-name] [clojure.data.xml.node :as xml-node] @@ -44,7 +45,7 @@ (deftest primitive-type->spec-defs-test - (testing "boolean" + (testing "Boolean" (is (= (-> (primitive-type "boolean") impl/primitive-type->spec-defs regexes->str) @@ -63,7 +64,7 @@ {:key :fhir.cbor/boolean :spec-form `(specs/cbor-primitive type/boolean)}]))) - (testing "integer" + (testing "Integer" (is (= (-> (primitive-type "integer") impl/primitive-type->spec-defs regexes->str) @@ -101,7 +102,7 @@ {:key :fhir.cbor/string :spec-form `(specs/cbor-primitive type/string)}]))) - (testing "decimal" + (testing "Decimal" (is (= (-> (primitive-type "decimal") impl/primitive-type->spec-defs regexes->str) diff --git a/modules/fhir-structure/test/blaze/fhir/spec/type_test.clj b/modules/fhir-structure/test/blaze/fhir/spec/type_test.clj index b0f91564b..759bf8304 100644 --- a/modules/fhir-structure/test/blaze/fhir/spec/type_test.clj +++ b/modules/fhir-structure/test/blaze/fhir/spec/type_test.clj @@ -122,7 +122,7 @@ #fhir/boolean true #fhir/boolean{:id "foo"})) - (testing "boolean" + (testing "Boolean" (is (= #fhir/boolean{:value true} #fhir/boolean true))) (testing "interned" @@ -197,7 +197,7 @@ #fhir/integer 1 #fhir/integer{:id "foo"})) - (testing "integer" + (testing "Integer" (is (= #fhir/integer{:value 1} #fhir/integer 1))) (testing "interned" @@ -253,7 +253,7 @@ #fhir/long 1 #fhir/long{:id "foo"})) - (testing "long" + (testing "Long" (is (= #fhir/long{:value 1} #fhir/long 1))) (testing "interned" @@ -372,7 +372,7 @@ #fhir/decimal 1M #fhir/decimal{:id "foo"})) - (testing "decimal" + (testing "Decimal" (is (= #fhir/decimal{:value 1M} #fhir/decimal 1M))) (testing "interned" diff --git a/modules/fhir-test-util/.clj-kondo/config.edn b/modules/fhir-test-util/.clj-kondo/config.edn new file mode 100644 index 000000000..52a3a2d2f --- /dev/null +++ b/modules/fhir-test-util/.clj-kondo/config.edn @@ -0,0 +1,23 @@ +{:lint-as + {blaze.fhir.spec.generators/def-resource-gen clojure.core/def} + + :linters + {:unsorted-required-namespaces + {:level :error} + + :single-key-in + {:level :warning} + + :keyword-binding + {:level :error} + + :reduce-without-init + {:level :warning} + + :unresolved-symbol + {:exclude [(blaze.fhir.spec.generators/def-resource-gen)]}} + + :warn-on-reflection + {:level :warning :warn-only-on-interop true} + + :skip-comments true} diff --git a/modules/fhir-test-util/Makefile b/modules/fhir-test-util/Makefile new file mode 100644 index 000000000..c6dcaacb7 --- /dev/null +++ b/modules/fhir-test-util/Makefile @@ -0,0 +1,13 @@ +lint: + clj-kondo --lint src deps.edn + +test: + true + +test-coverage: + true + +clean: + rm -rf .clj-kondo/.cache .cpcache target + +.PHONY: lint test test-coverage clean diff --git a/modules/fhir-test-util/deps.edn b/modules/fhir-test-util/deps.edn new file mode 100644 index 000000000..05a65d1a3 --- /dev/null +++ b/modules/fhir-test-util/deps.edn @@ -0,0 +1,18 @@ +{:deps + {blaze/anomaly + {:local/root "../anomaly"} + + blaze/async + {:local/root "../async"} + + blaze/byte-buffer + {:local/root "../byte-buffer"} + + blaze/executor + {:local/root "../executor"} + + blaze/fhir-structure + {:local/root "../fhir-structure"} + + blaze/module-test-util + {:local/root "../module-test-util"}}} diff --git a/modules/test-util/src/blaze/fhir/spec/generators.clj b/modules/fhir-test-util/src/blaze/fhir/spec/generators.clj similarity index 100% rename from modules/test-util/src/blaze/fhir/spec/generators.clj rename to modules/fhir-test-util/src/blaze/fhir/spec/generators.clj diff --git a/modules/fhir-test-util/src/blaze/fhir/test_util.clj b/modules/fhir-test-util/src/blaze/fhir/test_util.clj new file mode 100644 index 000000000..f1e4a5018 --- /dev/null +++ b/modules/fhir-test-util/src/blaze/fhir/test_util.clj @@ -0,0 +1,64 @@ +(ns blaze.fhir.test-util + (:require + [blaze.anomaly :as ba] + [blaze.byte-buffer :as bb] + [blaze.executors :as ex] + [blaze.fhir.structure-definition-repo] + [clojure.test :refer [is]] + [integrant.core :as ig] + [juxt.iota :refer [given]]) + (:import + [java.time Clock Instant ZoneId] + [java.util Random] + [java.util.concurrent Executors TimeUnit])) + + +(set! *warn-on-reflection* true) + + +(defmacro given-failed-future [future & body] + `(given (try (deref ~future) (is false) (catch Exception e# (ba/anomaly e#))) + ~@body)) + + +(defmethod ig/init-key :blaze.test/fixed-clock + [_ _] + (Clock/fixed Instant/EPOCH (ZoneId/of "UTC"))) + + +(defmethod ig/init-key :blaze.test/system-clock + [_ _] + (Clock/systemUTC)) + + +(defmethod ig/init-key :blaze.test/fixed-rng-fn + [_ {:keys [n] :or {n 0}}] + #(proxy [Random] [] + (nextLong [] n))) + + +(defmethod ig/init-key :blaze.test/fixed-rng + [_ _] + (let [state (atom 0)] + (proxy [Random] [] + (nextBytes [byte-array] + (assert (= 20 (count byte-array))) + (let [bb (bb/wrap byte-array)] + (bb/set-position! bb 12) + (bb/put-long! bb (swap! state inc))))))) + + +(defmethod ig/init-key :blaze.test/executor + [_ _] + (Executors/newFixedThreadPool 4)) + + +(defmethod ig/halt-key! :blaze.test/executor + [_ executor] + (ex/shutdown! executor) + (ex/await-termination executor 10 TimeUnit/SECONDS)) + + +(defonce structure-definition-repo + (:blaze.fhir/structure-definition-repo + (ig/init {:blaze.fhir/structure-definition-repo {}}))) diff --git a/modules/test-util/src/blaze/test_util/ring.clj b/modules/fhir-test-util/src/blaze/fhir/test_util/ring.clj similarity index 91% rename from modules/test-util/src/blaze/test_util/ring.clj rename to modules/fhir-test-util/src/blaze/fhir/test_util/ring.clj index 9f0d45a61..b1a49da60 100644 --- a/modules/test-util/src/blaze/test_util/ring.clj +++ b/modules/fhir-test-util/src/blaze/fhir/test_util/ring.clj @@ -1,4 +1,4 @@ -(ns blaze.test-util.ring +(ns blaze.fhir.test-util.ring (:require [blaze.async.comp :as ac])) diff --git a/modules/frontend/.clj-kondo/config.edn b/modules/frontend/.clj-kondo/config.edn index d8a0e4c97..c95b6452e 100644 --- a/modules/frontend/.clj-kondo/config.edn +++ b/modules/frontend/.clj-kondo/config.edn @@ -1,5 +1,5 @@ {:lint-as - {blaze.test-util/with-system clojure.core/with-open} + {blaze.module.test-util/with-system clojure.core/with-open} :linters {:unsorted-required-namespaces diff --git a/modules/frontend/Makefile b/modules/frontend/Makefile index aa397ab9c..4a294acc7 100644 --- a/modules/frontend/Makefile +++ b/modules/frontend/Makefile @@ -28,6 +28,6 @@ test-coverage: build clojure -M:test:coverage clean: - rm -rf .clj-kondo/.cache .cpcache target build + rm -rf .clj-kondo/.cache .cpcache target build node_modules .svelte-kit .PHONY: install update lint-js lint-clj lint check test-js build test test-coverage clean diff --git a/modules/frontend/clj/test/blaze/frontend_test.clj b/modules/frontend/clj/test/blaze/frontend_test.clj index ed4680c8a..96b2086d4 100644 --- a/modules/frontend/clj/test/blaze/frontend_test.clj +++ b/modules/frontend/clj/test/blaze/frontend_test.clj @@ -1,8 +1,9 @@ (ns blaze.frontend-test (:require + [blaze.fhir.test-util.ring :refer [call]] [blaze.frontend] - [blaze.test-util :as tu :refer [given-thrown with-system]] - [blaze.test-util.ring :refer [call]] + [blaze.module.test-util :refer [with-system]] + [blaze.test-util :as tu :refer [given-thrown]] [clojure.spec.alpha :as s] [clojure.spec.test.alpha :as st] [clojure.string :as str] diff --git a/modules/frontend/deps.edn b/modules/frontend/deps.edn index 91d91a9eb..37df43957 100644 --- a/modules/frontend/deps.edn +++ b/modules/frontend/deps.edn @@ -19,8 +19,8 @@ {:extra-paths ["clj/test"] :extra-deps - {blaze/test-util - {:local/root "../test-util"} + {blaze/fhir-test-util + {:local/root "../fhir-test-util"} org.clojars.akiel/iota {:mvn/version "0.1"}}} diff --git a/modules/frontend/package-lock.json b/modules/frontend/package-lock.json index 3d9e4c12a..bc9fca63f 100644 --- a/modules/frontend/package-lock.json +++ b/modules/frontend/package-lock.json @@ -1,12 +1,12 @@ { "name": "blaze-frontend", - "version": "0.22.0", + "version": "0.22.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "blaze-frontend", - "version": "0.22.0", + "version": "0.22.1", "dependencies": { "@fontsource/inter": "^4.5.15", "@tailwindcss/forms": "^0.5.3" diff --git a/modules/frontend/package.json b/modules/frontend/package.json index 722ab9409..5b8177731 100644 --- a/modules/frontend/package.json +++ b/modules/frontend/package.json @@ -1,6 +1,6 @@ { "name": "blaze-frontend", - "version": "0.22.0", + "version": "0.22.1", "private": true, "scripts": { "dev": "vite dev", diff --git a/modules/http-client/.clj-kondo/config.edn b/modules/http-client/.clj-kondo/config.edn index d12a895c1..a25d19101 100644 --- a/modules/http-client/.clj-kondo/config.edn +++ b/modules/http-client/.clj-kondo/config.edn @@ -1,5 +1,5 @@ {:lint-as - {blaze.test-util/with-system clojure.core/with-open} + {blaze.module.test-util/with-system clojure.core/with-open} :linters {:unsorted-required-namespaces diff --git a/modules/http-client/Makefile b/modules/http-client/Makefile index 8eb60f27a..196a53ceb 100644 --- a/modules/http-client/Makefile +++ b/modules/http-client/Makefile @@ -1,16 +1,13 @@ lint: clj-kondo --lint src test deps.edn -prep: - clojure -X:deps prep - -test: prep +test: clojure -M:test:kaocha --profile :ci -test-coverage: prep +test-coverage: clojure -M:test:coverage clean: rm -rf .clj-kondo/.cache .cpcache target -.PHONY: lint prep test test-coverage clean +.PHONY: lint test test-coverage clean diff --git a/modules/http-client/deps.edn b/modules/http-client/deps.edn index 8ce946ace..66d1704e7 100644 --- a/modules/http-client/deps.edn +++ b/modules/http-client/deps.edn @@ -3,9 +3,7 @@ {:local/root "../module-base"} cheshire/cheshire - {:mvn/version "5.11.0" - :exclusions - [com.fasterxml.jackson.dataformat/jackson-dataformat-cbor]} + {:mvn/version "5.11.0"} com.fasterxml.jackson.core/jackson-core {:mvn/version "2.15.2"} @@ -13,6 +11,9 @@ com.fasterxml.jackson.dataformat/jackson-dataformat-smile {:mvn/version "2.15.2"} + com.fasterxml.jackson.dataformat/jackson-dataformat-cbor + {:mvn/version "2.15.2"} + hato/hato {:mvn/version "0.9.0"}} @@ -21,8 +22,8 @@ {:extra-paths ["test"] :extra-deps - {blaze/test-util - {:local/root "../test-util"}}} + {blaze/module-test-util + {:local/root "../module-test-util"}}} :kaocha {:extra-deps diff --git a/modules/http-client/test/blaze/http_client_test.clj b/modules/http-client/test/blaze/http_client_test.clj index cb349e6f2..0d93b10f8 100644 --- a/modules/http-client/test/blaze/http_client_test.clj +++ b/modules/http-client/test/blaze/http_client_test.clj @@ -2,7 +2,8 @@ (:require [blaze.http-client] [blaze.http-client.spec] - [blaze.test-util :as tu :refer [given-thrown with-system]] + [blaze.module.test-util :refer [with-system]] + [blaze.test-util :as tu :refer [given-thrown]] [clojure.core.protocols :refer [Datafiable]] [clojure.datafy :refer [datafy]] [clojure.spec.alpha :as s] diff --git a/modules/interaction/.clj-kondo/config.edn b/modules/interaction/.clj-kondo/config.edn index 356392ad9..ce581c460 100644 --- a/modules/interaction/.clj-kondo/config.edn +++ b/modules/interaction/.clj-kondo/config.edn @@ -15,7 +15,7 @@ blaze.interaction.search-type-test/with-handler clojure.core/fn blaze.interaction.transaction-test/with-handler clojure.core/fn blaze.interaction.update-test/with-handler clojure.core/fn - blaze.test-util/with-system clojure.core/with-open} + blaze.module.test-util/with-system clojure.core/with-open} :linters {:unsorted-required-namespaces @@ -39,6 +39,7 @@ blaze.db.kv kv blaze.test-util tu blaze.util u + cognitect.anomalies anom cuerdas.core c-str ring.util.response ring}}} diff --git a/modules/interaction/src/blaze/interaction/history/util.clj b/modules/interaction/src/blaze/interaction/history/util.clj index e6d7faf74..cf78e8c6a 100644 --- a/modules/interaction/src/blaze/interaction/history/util.clj +++ b/modules/interaction/src/blaze/interaction/history/util.clj @@ -1,8 +1,8 @@ (ns blaze.interaction.history.util (:require + [blaze.db.api :as d] [blaze.fhir.spec.type :as type] [blaze.handler.fhir.util :as fhir-util] - [blaze.interaction.util :as iu] [blaze.util :as u] [reitit.core :as reitit]) (:import @@ -48,7 +48,7 @@ [{:blaze/keys [base-url db] ::reitit/keys [match]} query-params page-t & more] (let [path (reitit/match->path match - (cond-> (assoc query-params "__t" (iu/t db) "__page-t" page-t) + (cond-> (assoc query-params "__t" (d/t db) "__page-t" page-t) (= 1 (count more)) (assoc "__page-id" (first more)) (= 2 (count more)) diff --git a/modules/interaction/src/blaze/interaction/search_compartment.clj b/modules/interaction/src/blaze/interaction/search_compartment.clj index 21e18677d..45bd3b07e 100644 --- a/modules/interaction/src/blaze/interaction/search_compartment.clj +++ b/modules/interaction/src/blaze/interaction/search_compartment.clj @@ -54,7 +54,7 @@ {:keys [page-offset] :as params} :params} clauses] {:fhir/type :fhir.Bundle/link :relation "self" - :url (nav/url base-url match params clauses (iu/t db) + :url (nav/url base-url match params clauses (d/t db) {"__page-offset" page-offset})}) @@ -65,7 +65,7 @@ (defn- next-link [{:keys [page-store match params] :blaze/keys [base-url db]} clauses entries] (do-sync [url (nav/token-url! page-store base-url match params clauses - (iu/t db) (next-link-offset params entries))] + (d/t db) (next-link-offset params entries))] {:fhir/type :fhir.Bundle/link :relation "next" :url url})) diff --git a/modules/interaction/src/blaze/interaction/search_system.clj b/modules/interaction/src/blaze/interaction/search_system.clj index 8214793f0..608713e0c 100644 --- a/modules/interaction/src/blaze/interaction/search_system.clj +++ b/modules/interaction/src/blaze/interaction/search_system.clj @@ -50,7 +50,7 @@ (defn- self-link [{:keys [match params] :blaze/keys [base-url db]} entries] {:fhir/type :fhir.Bundle/link :relation "self" - :url (nav/url base-url match params [] (iu/t db) (self-link-offset entries))}) + :url (nav/url base-url match params [] (d/t db) (self-link-offset entries))}) (defn- next-link-offset [entries] @@ -61,7 +61,7 @@ (defn- next-link [{:keys [page-store page-match params] :blaze/keys [base-url db]} entries] (do-sync [url (nav/token-url! page-store base-url page-match params [] - (iu/t db) (next-link-offset entries))] + (d/t db) (next-link-offset entries))] {:fhir/type :fhir.Bundle/link :relation "next" :url url})) diff --git a/modules/interaction/src/blaze/interaction/search_type.clj b/modules/interaction/src/blaze/interaction/search_type.clj index 495798e4c..728802a2e 100644 --- a/modules/interaction/src/blaze/interaction/search_type.clj +++ b/modules/interaction/src/blaze/interaction/search_type.clj @@ -267,7 +267,7 @@ (defn- self-link-url-fn [{:blaze/keys [base-url db] :as request} params] (fn [clauses offset] - (nav/url base-url (match request "type") params clauses (iu/t db) offset))) + (nav/url base-url (match request "type") params clauses (d/t db) offset))) (defn- gen-token-fn @@ -287,7 +287,7 @@ [{:blaze/keys [base-url db] :as request} params] (fn [token clauses] (nav/token-url base-url (match request "page") params token clauses - (iu/t db) nil))) + (d/t db) nil))) (defn- next-link-url-fn @@ -296,7 +296,7 @@ [{:blaze/keys [base-url db] :as request} params] (fn [token clauses offset] (nav/token-url base-url (match request "page") params token clauses - (iu/t db) offset))) + (d/t db) offset))) (defn- search-context diff --git a/modules/interaction/src/blaze/interaction/transaction/bundle/links.clj b/modules/interaction/src/blaze/interaction/transaction/bundle/links.clj index 43ba24617..6bb1dc29e 100644 --- a/modules/interaction/src/blaze/interaction/transaction/bundle/links.clj +++ b/modules/interaction/src/blaze/interaction/transaction/bundle/links.clj @@ -4,9 +4,11 @@ [blaze.fhir.spec.type :as type])) -(defn- resolve-link [index link] - (if-let [{:fhir/keys [type] :keys [id]} (get index link)] - (str (name type) "/" id) +(defn- resolve-link [index creator link] + (if-let [{:fhir/keys [type] :keys [id]} (get index (type/value link))] + (if (record? link) + (assoc link :value (str (name type) "/" id)) + (creator (str (name type) "/" id))) link)) @@ -18,9 +20,13 @@ (let [type (fhir-spec/fhir-type value)] (cond (identical? :fhir/Reference type) - (if-let [reference (:reference value)] - (assoc value :reference (resolve-link index reference)) - value) + (update value :reference (partial resolve-link index type/string)) + + (identical? :fhir/uri type) + (resolve-link index type/uri value) + + (identical? :fhir/url type) + (resolve-link index type/url value) (fhir-spec/primitive? type) value @@ -31,7 +37,7 @@ (defn- resolve-element-links [context value] (if (sequential? value) - (mapv #(resolve-single-element-links context %) value) + (mapv (partial resolve-single-element-links context) value) (resolve-single-element-links context value))) @@ -49,7 +55,9 @@ (defn- index-resources-by-full-url [entries] (reduce (fn [r {:keys [fullUrl resource]}] - (assoc r (some-> fullUrl type/value) resource)) + (if-let [fullUrl (type/value fullUrl)] + (assoc r fullUrl resource) + r)) {} entries)) diff --git a/modules/interaction/src/blaze/interaction/util.clj b/modules/interaction/src/blaze/interaction/util.clj index 2413cd7f3..e8cbe0d15 100644 --- a/modules/interaction/src/blaze/interaction/util.clj +++ b/modules/interaction/src/blaze/interaction/util.clj @@ -61,12 +61,6 @@ (luid/successive-luids clock (rng-fn))) -(defn t - "Returns the effective `t` of `db`." - [db] - (or (d/as-of-t db) (d/basis-t db))) - - (defn- prep-if-none-match [if-none-match] (if (= "*" if-none-match) :any diff --git a/modules/interaction/test/blaze/interaction/create_test.clj b/modules/interaction/test/blaze/interaction/create_test.clj index 4f4f259b3..4e374a1d7 100644 --- a/modules/interaction/test/blaze/interaction/create_test.clj +++ b/modules/interaction/test/blaze/interaction/create_test.clj @@ -8,8 +8,7 @@ [blaze.anomaly :as ba] [blaze.anomaly-spec] [blaze.async.comp :as ac] - [blaze.db.api-stub - :refer [create-mem-node-config with-system-data]] + [blaze.db.api-stub :as api-stub :refer [with-system-data]] [blaze.db.resource-store :as rs] [blaze.db.spec :refer [node?]] [blaze.fhir.response.create-spec] @@ -18,7 +17,8 @@ [blaze.interaction.test-util :refer [wrap-error]] [blaze.interaction.util-spec] [blaze.log] - [blaze.test-util :as tu :refer [given-thrown with-system]] + [blaze.module.test-util :refer [with-system]] + [blaze.test-util :as tu :refer [given-thrown]] [clojure.spec.alpha :as s] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [deftest is testing]] @@ -76,7 +76,7 @@ (defn create-config [node-config] - (assoc (create-mem-node-config node-config) + (assoc (api-stub/create-mem-node-config node-config) :blaze.interaction/create {:node (ig/ref :blaze.db/node) :executor (ig/ref :blaze.test/executor) @@ -99,7 +99,7 @@ (defmacro with-handler [[handler-binding] & more] - (let [[txs body] (tu/extract-txs-body more)] + (let [[txs body] (api-stub/extract-txs-body more)] `(with-system-data [{handler# :blaze.interaction/create} config] ~txs (let [~handler-binding (-> handler# wrap-defaults wrap-error)] diff --git a/modules/interaction/test/blaze/interaction/delete_test.clj b/modules/interaction/test/blaze/interaction/delete_test.clj index 4e85b763d..7eed64d1f 100644 --- a/modules/interaction/test/blaze/interaction/delete_test.clj +++ b/modules/interaction/test/blaze/interaction/delete_test.clj @@ -3,7 +3,7 @@ https://www.hl7.org/fhir/http.html#delete" (:require - [blaze.db.api-stub :refer [mem-node-config with-system-data]] + [blaze.db.api-stub :as api-stub :refer [with-system-data]] [blaze.db.spec :refer [node?]] [blaze.interaction.delete] [blaze.log] @@ -45,7 +45,7 @@ (def config - (assoc mem-node-config + (assoc api-stub/mem-node-config :blaze.interaction/delete {:node (ig/ref :blaze.db/node) :executor (ig/ref :blaze.test/executor)} @@ -53,7 +53,7 @@ (defmacro with-handler [[handler-binding] & more] - (let [[txs body] (tu/extract-txs-body more)] + (let [[txs body] (api-stub/extract-txs-body more)] `(with-system-data [{handler# :blaze.interaction/delete} config] ~txs (let [~handler-binding handler#] diff --git a/modules/interaction/test/blaze/interaction/history/instance_test.clj b/modules/interaction/test/blaze/interaction/history/instance_test.clj index c32ad50e7..e2ccb03fd 100644 --- a/modules/interaction/test/blaze/interaction/history/instance_test.clj +++ b/modules/interaction/test/blaze/interaction/history/instance_test.clj @@ -7,7 +7,7 @@ (:require [blaze.anomaly-spec] [blaze.async.comp :as ac] - [blaze.db.api-stub :refer [mem-node-config with-system-data]] + [blaze.db.api-stub :as api-stub :refer [with-system-data]] [blaze.db.resource-store :as rs] [blaze.interaction.history.instance] [blaze.interaction.history.util-spec] @@ -77,7 +77,7 @@ (def config - (assoc mem-node-config + (assoc api-stub/mem-node-config :blaze.interaction.history/instance {:node (ig/ref :blaze.db/node) :clock (ig/ref :blaze.test/fixed-clock) @@ -95,7 +95,7 @@ (defmacro with-handler [[handler-binding] & more] - (let [[txs body] (tu/extract-txs-body more)] + (let [[txs body] (api-stub/extract-txs-body more)] `(with-system-data [{node# :blaze.db/node handler# :blaze.interaction.history/instance} config] ~txs diff --git a/modules/interaction/test/blaze/interaction/history/system_test.clj b/modules/interaction/test/blaze/interaction/history/system_test.clj index 017247b94..921b17369 100644 --- a/modules/interaction/test/blaze/interaction/history/system_test.clj +++ b/modules/interaction/test/blaze/interaction/history/system_test.clj @@ -6,7 +6,7 @@ https://www.hl7.org/fhir/http.html#ops" (:require [blaze.async.comp :as ac] - [blaze.db.api-stub :refer [mem-node-config with-system-data]] + [blaze.db.api-stub :as api-stub :refer [with-system-data]] [blaze.db.resource-store :as rs] [blaze.interaction.history.system] [blaze.interaction.history.util-spec] @@ -79,7 +79,7 @@ (def config - (assoc mem-node-config + (assoc api-stub/mem-node-config :blaze.interaction.history/system {:node (ig/ref :blaze.db/node) :clock (ig/ref :blaze.test/fixed-clock) @@ -97,7 +97,7 @@ (defmacro with-handler [[handler-binding] & more] - (let [[txs body] (tu/extract-txs-body more)] + (let [[txs body] (api-stub/extract-txs-body more)] `(with-system-data [{node# :blaze.db/node handler# :blaze.interaction.history/system} config] ~txs diff --git a/modules/interaction/test/blaze/interaction/history/type_test.clj b/modules/interaction/test/blaze/interaction/history/type_test.clj index 54e883f8f..2047728c2 100644 --- a/modules/interaction/test/blaze/interaction/history/type_test.clj +++ b/modules/interaction/test/blaze/interaction/history/type_test.clj @@ -6,7 +6,7 @@ https://www.hl7.org/fhir/http.html#ops" (:require [blaze.async.comp :as ac] - [blaze.db.api-stub :refer [mem-node-config with-system-data]] + [blaze.db.api-stub :as api-stub :refer [with-system-data]] [blaze.db.resource-store :as rs] [blaze.interaction.history.type] [blaze.interaction.history.util-spec] @@ -80,7 +80,7 @@ (def config - (assoc mem-node-config + (assoc api-stub/mem-node-config :blaze.interaction.history/type {:node (ig/ref :blaze.db/node) :clock (ig/ref :blaze.test/fixed-clock) @@ -98,7 +98,7 @@ (defmacro with-handler [[handler-binding] & more] - (let [[txs body] (tu/extract-txs-body more)] + (let [[txs body] (api-stub/extract-txs-body more)] `(with-system-data [{node# :blaze.db/node handler# :blaze.interaction.history/type} config] ~txs diff --git a/modules/interaction/test/blaze/interaction/read_test.clj b/modules/interaction/test/blaze/interaction/read_test.clj index 4da4d4460..b1bca3c54 100644 --- a/modules/interaction/test/blaze/interaction/read_test.clj +++ b/modules/interaction/test/blaze/interaction/read_test.clj @@ -7,7 +7,7 @@ (:require [blaze.anomaly-spec] [blaze.async.comp :as ac] - [blaze.db.api-stub :refer [mem-node-config with-system-data]] + [blaze.db.api-stub :as api-stub :refer [with-system-data]] [blaze.db.resource-store :as rs] [blaze.db.spec] [blaze.interaction.read] @@ -32,7 +32,7 @@ (def config - (assoc mem-node-config :blaze.interaction/read {})) + (assoc api-stub/mem-node-config :blaze.interaction/read {})) (def match @@ -49,7 +49,7 @@ (defmacro with-handler [[handler-binding] & more] - (let [[txs body] (tu/extract-txs-body more)] + (let [[txs body] (api-stub/extract-txs-body more)] `(with-system-data [{node# :blaze.db/node handler# :blaze.interaction/read} config] ~txs @@ -59,7 +59,7 @@ (defmacro with-vread-handler [[handler-binding] & more] - (let [[txs body] (tu/extract-txs-body more)] + (let [[txs body] (api-stub/extract-txs-body more)] `(with-system-data [{node# :blaze.db/node handler# :blaze.interaction/read} config] ~txs diff --git a/modules/interaction/test/blaze/interaction/search/params_test.clj b/modules/interaction/test/blaze/interaction/search/params_test.clj index 66f9ca6d0..beb00205d 100644 --- a/modules/interaction/test/blaze/interaction/search/params_test.clj +++ b/modules/interaction/test/blaze/interaction/search/params_test.clj @@ -2,10 +2,11 @@ (:require [blaze.anomaly :as ba] [blaze.async.comp :as ac] + [blaze.fhir.test-util :refer [given-failed-future]] [blaze.interaction.search.params :as params] [blaze.interaction.search.params-spec] [blaze.page-store.protocols :as p] - [blaze.test-util :as tu :refer [given-failed-future]] + [blaze.test-util :as tu] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [deftest testing]] [cognitect.anomalies :as anom] diff --git a/modules/interaction/test/blaze/interaction/search_compartment_test.clj b/modules/interaction/test/blaze/interaction/search_compartment_test.clj index 552fcabc1..a712e66d5 100644 --- a/modules/interaction/test/blaze/interaction/search_compartment_test.clj +++ b/modules/interaction/test/blaze/interaction/search_compartment_test.clj @@ -4,7 +4,7 @@ https://www.hl7.org/fhir/http.html#vsearch" (:require [blaze.async.comp :as ac] - [blaze.db.api-stub :refer [mem-node-config with-system-data]] + [blaze.db.api-stub :as api-stub :refer [with-system-data]] [blaze.db.resource-store :as rs] [blaze.fhir.spec.type] [blaze.interaction.search-compartment] @@ -83,7 +83,7 @@ (def config - (assoc mem-node-config + (assoc api-stub/mem-node-config :blaze.interaction/search-compartment {:clock (ig/ref :blaze.test/fixed-clock) :rng-fn (ig/ref :blaze.test/fixed-rng-fn) @@ -103,7 +103,7 @@ (defmacro with-handler [[handler-binding] & more] - (let [[txs body] (tu/extract-txs-body more)] + (let [[txs body] (api-stub/extract-txs-body more)] `(with-system-data [{node# :blaze.db/node handler# :blaze.interaction/search-compartment} config] ~txs diff --git a/modules/interaction/test/blaze/interaction/search_system_test.clj b/modules/interaction/test/blaze/interaction/search_system_test.clj index 6fb0ade46..f6bdd120f 100644 --- a/modules/interaction/test/blaze/interaction/search_system_test.clj +++ b/modules/interaction/test/blaze/interaction/search_system_test.clj @@ -5,7 +5,7 @@ (:require [blaze.async.comp :as ac] [blaze.db.api :as d] - [blaze.db.api-stub :refer [mem-node-config with-system-data]] + [blaze.db.api-stub :as api-stub :refer [with-system-data]] [blaze.db.resource-store :as rs] [blaze.interaction.search-system] [blaze.interaction.search.nav-spec] @@ -91,7 +91,7 @@ (def config - (assoc mem-node-config + (assoc api-stub/mem-node-config :blaze.interaction/search-system {:node (ig/ref :blaze.db/node) :clock (ig/ref :blaze.test/fixed-clock) @@ -119,7 +119,7 @@ (defmacro with-handler [[handler-binding & [node-binding]] & more] - (let [[txs body] (tu/extract-txs-body more)] + (let [[txs body] (api-stub/extract-txs-body more)] `(with-system-data [{node# :blaze.db/node handler# :blaze.interaction/search-system} config] ~txs diff --git a/modules/interaction/test/blaze/interaction/search_type_test.clj b/modules/interaction/test/blaze/interaction/search_type_test.clj index a5beda5f4..acabe0638 100644 --- a/modules/interaction/test/blaze/interaction/search_type_test.clj +++ b/modules/interaction/test/blaze/interaction/search_type_test.clj @@ -5,7 +5,7 @@ (:require [blaze.async.comp :as ac] [blaze.db.api :as d] - [blaze.db.api-stub :refer [mem-node-config with-system-data]] + [blaze.db.api-stub :as api-stub :refer [with-system-data]] [blaze.db.resource-store :as rs] [blaze.fhir.spec :as fhir-spec] [blaze.fhir.spec.type :as type] @@ -163,7 +163,7 @@ (def config - (assoc mem-node-config + (assoc api-stub/mem-node-config :blaze.interaction/search-type {:clock (ig/ref :blaze.test/fixed-clock) :rng-fn (ig/ref :blaze.test/fixed-rng-fn) @@ -189,7 +189,7 @@ (defmacro with-handler [[handler-binding & [node-binding]] & more] - (let [[txs body] (tu/extract-txs-body more)] + (let [[txs body] (api-stub/extract-txs-body more)] `(with-system-data [{node# :blaze.db/node handler# :blaze.interaction/search-type} config] ~txs diff --git a/modules/interaction/test/blaze/interaction/transaction/bundle/links_test.clj b/modules/interaction/test/blaze/interaction/transaction/bundle/links_test.clj index 95e887536..08ffda49d 100644 --- a/modules/interaction/test/blaze/interaction/transaction/bundle/links_test.clj +++ b/modules/interaction/test/blaze/interaction/transaction/bundle/links_test.clj @@ -24,64 +24,289 @@ :id "0" :subject #fhir/Reference - {:reference "urn:uuid:d7bd0ece-fe3c-4755-b7c9-5b86f42e304a"}} + {:reference #fhir/string"urn:uuid:d7bd0ece-fe3c-4755-b7c9-5b86f42e304a"}} :request {:method #fhir/code"POST" :url #fhir/uri"Observation"}} {:fullUrl #fhir/uri"urn:uuid:d7bd0ece-fe3c-4755-b7c9-5b86f42e304a" :resource {:fhir/type :fhir/Patient - :id "0"} + :id "160210"} :request {:method #fhir/code"POST" :url #fhir/uri"Patient"}}]] (given (links/resolve-entry-links entries) - [0 :resource :subject :reference] := "Patient/0"))) + [0 :resource :subject :reference] := #fhir/string"Patient/160210")) + + (testing "preserving the id on the Reference.reference" + (let [entries + [{:fullUrl #fhir/uri"urn:uuid:9ef14708-5695-4aad-8623-8c8ebd4f48ee" + :resource + {:fhir/type :fhir/Observation + :id "0" + :subject + #fhir/Reference + {:reference #fhir/string{:id "id-211320" + :value "urn:uuid:d7bd0ece-fe3c-4755-b7c9-5b86f42e304a"}}} + :request + {:method #fhir/code"POST" + :url #fhir/uri"Observation"}} + {:fullUrl #fhir/uri"urn:uuid:d7bd0ece-fe3c-4755-b7c9-5b86f42e304a" + :resource + {:fhir/type :fhir/Patient + :id "160210"} + :request + {:method #fhir/code"POST" + :url #fhir/uri"Patient"}}]] + (given (links/resolve-entry-links entries) + [0 :resource :subject :reference] := #fhir/string{:id "id-211320" + :value "Patient/160210"})))) (testing "Patient.generalPractitioner reference" (let [entries - [{:fullUrl #fhir/uri"urn:uuid:44dded80-aaf1-4988-ace4-5f3a2c9935a7" - :resource - {:fhir/type :fhir/Organization - :id "0"} - :request - {:method #fhir/code"POST" - :url #fhir/uri"Organization"}} - {:fullUrl #fhir/uri"urn:uuid:61f73804-78da-4865-8c28-73bdf6f05a2e" + [{:fullUrl #fhir/uri"urn:uuid:61f73804-78da-4865-8c28-73bdf6f05a2e" :resource {:fhir/type :fhir/Patient :id "0" :generalPractitioner [#fhir/Reference - {:reference "urn:uuid:44dded80-aaf1-4988-ace4-5f3a2c9935a7"}]} + {:reference #fhir/string"urn:uuid:44dded80-aaf1-4988-ace4-5f3a2c9935a7"}]} :request {:method #fhir/code"POST" - :url #fhir/uri"Patient"}}]] + :url #fhir/uri"Patient"}} + {:fullUrl #fhir/uri"urn:uuid:44dded80-aaf1-4988-ace4-5f3a2c9935a7" + :resource + {:fhir/type :fhir/Organization + :id "160200"} + :request + {:method #fhir/code"POST" + :url #fhir/uri"Organization"}}]] (given (links/resolve-entry-links entries) - [1 :resource :generalPractitioner 0 :reference] := "Organization/0"))) + [0 :resource :generalPractitioner 0 :reference] := #fhir/string"Organization/160200"))) (testing "Claim.diagnosis.diagnosisReference reference" (let [entries - [{:fullUrl #fhir/uri"urn:uuid:69857788-8691-45b9-bc97-654fb93ba615" - :resource - {:fhir/type :fhir/Condition - :id "0"} - :request - {:method #fhir/code"POST" - :url "Condition"}} - {:fullUrl #fhir/uri"urn:uuid:44cf9905-f381-4849-8a35-79a6b29ae1b5" + [{:fullUrl #fhir/uri"urn:uuid:44cf9905-f381-4849-8a35-79a6b29ae1b5" :resource {:fhir/type :fhir/Claim :id "0" :diagnosis [{:diagnosisReference #fhir/Reference - {:reference "urn:uuid:69857788-8691-45b9-bc97-654fb93ba615"}}]} + {:reference #fhir/string"urn:uuid:69857788-8691-45b9-bc97-654fb93ba615"}}]} + :request + {:method #fhir/code"POST" + :url #fhir/uri"Claim"}} + {:fullUrl #fhir/uri"urn:uuid:69857788-8691-45b9-bc97-654fb93ba615" + :resource + {:fhir/type :fhir/Condition + :id "160146"} :request {:method #fhir/code"POST" - :url #fhir/uri"Claim"}}]] + :url #fhir/uri"Condition"}}]] (given (links/resolve-entry-links entries) - [1 :resource :diagnosis 0 :diagnosisReference :reference] := "Condition/0"))) + [0 :resource :diagnosis 0 :diagnosisReference :reference] := #fhir/string"Condition/160146"))) + + (testing "Attachment.url" + (testing "resolves the Binary resource" + (let [entries + [{:fullUrl #fhir/uri"urn:uuid:44cf9905-f381-4849-8a35-79a6b29ae1b5" + :resource + {:fhir/type :fhir/DocumentReference + :id "0" + :content + [{:fhir/type :fhir.DocumentReference/content + :attachment + #fhir/Attachment{:url #fhir/url"urn:uuid:5b016a4d-d393-48df-8d92-7ac4d1b8e56d"}}]} + :request + {:method #fhir/code"POST" + :url #fhir/uri"DocumentReference"}} + {:fullUrl #fhir/uri"urn:uuid:5b016a4d-d393-48df-8d92-7ac4d1b8e56d" + :resource + {:fhir/type :fhir/Binary + :id "160527"} + :request + {:method #fhir/code"POST" + :url #fhir/uri"Binary"}}]] + (given (links/resolve-entry-links entries) + [0 :resource :content 0 :attachment :url] := #fhir/url"Binary/160527")) + + (testing "preserving the id on the URL" + (let [entries + [{:fullUrl #fhir/uri"urn:uuid:44cf9905-f381-4849-8a35-79a6b29ae1b5" + :resource + {:fhir/type :fhir/DocumentReference + :id "0" + :content + [{:fhir/type :fhir.DocumentReference/content + :attachment + #fhir/Attachment + {:url #fhir/url + {:id "id-204917" + :value "urn:uuid:5b016a4d-d393-48df-8d92-7ac4d1b8e56d"}}}]} + :request + {:method #fhir/code"POST" + :url #fhir/uri"DocumentReference"}} + {:fullUrl #fhir/uri"urn:uuid:5b016a4d-d393-48df-8d92-7ac4d1b8e56d" + :resource + {:fhir/type :fhir/Binary + :id "160527"} + :request + {:method #fhir/code"POST" + :url #fhir/uri"Binary"}}]] + (given (links/resolve-entry-links entries) + [0 :resource :content 0 :attachment :url] := #fhir/url{:id "id-204917" + :value "Binary/160527"}))) + + (testing "preserving the extension on the URL" + (let [entries + [{:fullUrl #fhir/uri"urn:uuid:44cf9905-f381-4849-8a35-79a6b29ae1b5" + :resource + {:fhir/type :fhir/DocumentReference + :id "0" + :content + [{:fhir/type :fhir.DocumentReference/content + :attachment + #fhir/Attachment + {:url #fhir/url + {:extension #fhir/Extension{:url "foo"} + :value "urn:uuid:5b016a4d-d393-48df-8d92-7ac4d1b8e56d"}}}]} + :request + {:method #fhir/code"POST" + :url #fhir/uri"DocumentReference"}} + {:fullUrl #fhir/uri"urn:uuid:5b016a4d-d393-48df-8d92-7ac4d1b8e56d" + :resource + {:fhir/type :fhir/Binary + :id "160527"} + :request + {:method #fhir/code"POST" + :url #fhir/uri"Binary"}}]] + (given (links/resolve-entry-links entries) + [0 :resource :content 0 :attachment :url] := #fhir/url{:extension #fhir/Extension{:url "foo"} + :value "Binary/160527"})))) + + (testing "does nothing at not found URL value" + (let [entries + [{:fullUrl #fhir/uri"urn:uuid:44cf9905-f381-4849-8a35-79a6b29ae1b5" + :resource + {:fhir/type :fhir/DocumentReference + :id "0" + :content + [{:fhir/type :fhir.DocumentReference/content + :attachment + #fhir/Attachment{:url #fhir/url"urn:uuid:839c8ffb-de0b-4835-8edf-9d3d2e14d9a7"}}]} + :request + {:method #fhir/code"POST" + :url #fhir/uri"DocumentReference"}}]] + (given (links/resolve-entry-links entries) + [0 :resource :content 0 :attachment :url] := #fhir/url"urn:uuid:839c8ffb-de0b-4835-8edf-9d3d2e14d9a7"))) + + (testing "does nothing at missing URL value" + (let [entries + [{:fullUrl #fhir/uri"urn:uuid:44cf9905-f381-4849-8a35-79a6b29ae1b5" + :resource + {:fhir/type :fhir/DocumentReference + :id "0" + :content + [{:fhir/type :fhir.DocumentReference/content + :attachment + #fhir/Attachment{:url #fhir/url{:id "foo"}}}]} + :request + {:method #fhir/code"POST" + :url #fhir/uri"DocumentReference"}}]] + (given (links/resolve-entry-links entries) + [0 :resource :content 0 :attachment :url] := #fhir/url{:id "foo"})))) + + (testing "ConceptMap.source" + (testing "resolves the ValueSet resource" + (let [entries + [{:fullUrl #fhir/uri"urn:uuid:44cf9905-f381-4849-8a35-79a6b29ae1b5" + :resource + {:fhir/type :fhir/ConceptMap + :id "0" + :source #fhir/uri"urn:uuid:76566123-cf61-440b-98f5-7eda0bfde07a"} + :request + {:method #fhir/code"POST" + :url #fhir/uri"ConceptMap"}} + {:fullUrl #fhir/uri"urn:uuid:76566123-cf61-440b-98f5-7eda0bfde07a" + :resource + {:fhir/type :fhir/ValueSet + :id "165422"} + :request + {:method #fhir/code"POST" + :url #fhir/uri"ValueSet"}}]] + (given (links/resolve-entry-links entries) + [0 :resource :source] := #fhir/uri"ValueSet/165422")) + + (testing "preserving the id on the URI" + (let [entries + [{:fullUrl #fhir/uri"urn:uuid:44cf9905-f381-4849-8a35-79a6b29ae1b5" + :resource + {:fhir/type :fhir/ConceptMap + :id "0" + :source #fhir/uri{:id "id-205412" + :value "urn:uuid:76566123-cf61-440b-98f5-7eda0bfde07a"}} + :request + {:method #fhir/code"POST" + :url #fhir/uri"ConceptMap"}} + {:fullUrl #fhir/uri"urn:uuid:76566123-cf61-440b-98f5-7eda0bfde07a" + :resource + {:fhir/type :fhir/ValueSet + :id "165422"} + :request + {:method #fhir/code"POST" + :url #fhir/uri"ValueSet"}}]] + (given (links/resolve-entry-links entries) + [0 :resource :source] := #fhir/uri{:id "id-205412" + :value "ValueSet/165422"}))) + + (testing "preserving the extension on the URI" + (let [entries + [{:fullUrl #fhir/uri"urn:uuid:44cf9905-f381-4849-8a35-79a6b29ae1b5" + :resource + {:fhir/type :fhir/ConceptMap + :id "0" + :source #fhir/uri{:extension #fhir/Extension{:url "foo"} + :value "urn:uuid:76566123-cf61-440b-98f5-7eda0bfde07a"}} + :request + {:method #fhir/code"POST" + :url #fhir/uri"ConceptMap"}} + {:fullUrl #fhir/uri"urn:uuid:76566123-cf61-440b-98f5-7eda0bfde07a" + :resource + {:fhir/type :fhir/ValueSet + :id "165422"} + :request + {:method #fhir/code"POST" + :url #fhir/uri"ValueSet"}}]] + (given (links/resolve-entry-links entries) + [0 :resource :source] := #fhir/uri{:extension #fhir/Extension{:url "foo"} + :value "ValueSet/165422"})))) + + (testing "does nothing at not found URI value" + (let [entries + [{:fullUrl #fhir/uri"urn:uuid:44cf9905-f381-4849-8a35-79a6b29ae1b5" + :resource + {:fhir/type :fhir/ConceptMap + :id "0" + :source #fhir/uri"urn:uuid:84a95644-82d8-48bc-85a4-36e7d80d176b"} + :request + {:method #fhir/code"POST" + :url #fhir/uri"ConceptMap"}}]] + (given (links/resolve-entry-links entries) + [0 :resource :source] := #fhir/uri"urn:uuid:84a95644-82d8-48bc-85a4-36e7d80d176b"))) + + (testing "does nothing at missing URI value" + (let [entries + [{:fullUrl #fhir/uri"urn:uuid:44cf9905-f381-4849-8a35-79a6b29ae1b5" + :resource + {:fhir/type :fhir/ConceptMap + :id "0" + :source #fhir/uri{:id "foo"}} + :request + {:method #fhir/code"POST" + :url #fhir/uri"ConceptMap"}}]] + (given (links/resolve-entry-links entries) + [0 :resource :source] := #fhir/uri{:id "foo"})))) (testing "preserves complex-type records" (let [entries @@ -89,7 +314,15 @@ {:fhir/type :fhir/Observation :id "0" :code #fhir/CodeableConcept{}}}]] (given (links/resolve-entry-links entries) - [0 :resource :code fhir-spec/fhir-type] := :fhir/CodeableConcept)))) + [0 :resource :code fhir-spec/fhir-type] := :fhir/CodeableConcept))) + + (testing "preserves references without reference" + (let [entries + [{:resource + {:fhir/type :fhir/Observation :id "0" + :subject #fhir/Reference{:display "foo"}}}]] + (given (links/resolve-entry-links entries) + [0 :resource :subject] := #fhir/Reference{:display "foo"})))) (deftest resolve-entry-links-in-contained-resources-test diff --git a/modules/interaction/test/blaze/interaction/transaction/bundle_test.clj b/modules/interaction/test/blaze/interaction/transaction/bundle_test.clj index e25f0685e..9982c5639 100644 --- a/modules/interaction/test/blaze/interaction/transaction/bundle_test.clj +++ b/modules/interaction/test/blaze/interaction/transaction/bundle_test.clj @@ -5,7 +5,8 @@ [blaze.fhir.spec.type :as type] [blaze.interaction.transaction.bundle :as bundle] [blaze.interaction.transaction.bundle-spec] - [blaze.test-util :as tu :refer [with-system]] + [blaze.module.test-util :refer [with-system]] + [blaze.test-util :as tu] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [deftest testing]] [cognitect.anomalies :as anom] diff --git a/modules/interaction/test/blaze/interaction/transaction_test.clj b/modules/interaction/test/blaze/interaction/transaction_test.clj index d7f95edfb..53d6095de 100644 --- a/modules/interaction/test/blaze/interaction/transaction_test.clj +++ b/modules/interaction/test/blaze/interaction/transaction_test.clj @@ -6,7 +6,7 @@ https://www.hl7.org/fhir/http.html#ops" (:require [blaze.async.comp :as ac] - [blaze.db.api-stub :refer [mem-node-config with-system-data]] + [blaze.db.api-stub :as api-stub :refer [with-system-data]] [blaze.db.kv :as kv] [blaze.db.node :as node] [blaze.db.resource-store :as rs] @@ -131,7 +131,7 @@ (def config - (assoc mem-node-config + (assoc api-stub/mem-node-config :blaze.interaction/transaction {:node (ig/ref :blaze.db/node) :clock (ig/ref :blaze.test/fixed-clock) @@ -180,7 +180,7 @@ (defmacro with-handler [[handler-binding & [node-binding]] & more] - (let [[txs body] (tu/extract-txs-body more)] + (let [[txs body] (api-stub/extract-txs-body more)] `(with-system-data [{handler# :blaze.interaction/transaction router# ::router node# :blaze.db/node} config] @@ -1542,6 +1542,35 @@ :url #fhir/uri"Patient"}}]}})] (given body [:entry 0 :resource :id] := "AAAAAAAAAAAAAAAA" + [:entry 1 :resource :id] := "AAAAAAAAAAAAAAAB")))) + + (testing "resolves links" + (with-handler [handler] + (let [{:keys [body]} + @(handler + {:headers {"prefer" "return=representation"} + :body + {:fhir/type :fhir/Bundle + :type #fhir/code"transaction" + :entry + [{:fullUrl #fhir/uri"urn:uuid:44cf9905-f381-4849-8a35-79a6b29ae1b5" + :resource + {:fhir/type :fhir/DocumentReference + :content + [{:fhir/type :fhir.DocumentReference/content + :attachment + #fhir/Attachment{:url #fhir/url"urn:uuid:5b016a4d-d393-48df-8d92-7ac4d1b8e56d"}}]} + :request + {:method #fhir/code"POST" + :url #fhir/uri"DocumentReference"}} + {:fullUrl #fhir/uri"urn:uuid:5b016a4d-d393-48df-8d92-7ac4d1b8e56d" + :resource + {:fhir/type :fhir/Binary} + :request + {:method #fhir/code"POST" + :url #fhir/uri"Binary"}}]}})] + (given body + [:entry 0 :resource :content 0 :attachment :url] := #fhir/url"Binary/AAAAAAAAAAAAAAAB" [:entry 1 :resource :id] := "AAAAAAAAAAAAAAAB"))))) (testing "and conditional create interaction" diff --git a/modules/interaction/test/blaze/interaction/update_test.clj b/modules/interaction/test/blaze/interaction/update_test.clj index 9c3c08a2d..3f72abcb4 100644 --- a/modules/interaction/test/blaze/interaction/update_test.clj +++ b/modules/interaction/test/blaze/interaction/update_test.clj @@ -7,7 +7,7 @@ (:require [blaze.anomaly-spec] [blaze.async.comp :as ac] - [blaze.db.api-stub :refer [mem-node-config with-system-data]] + [blaze.db.api-stub :as api-stub :refer [with-system-data]] [blaze.db.kv :as kv] [blaze.db.node :as node] [blaze.db.resource-store :as rs] @@ -83,7 +83,7 @@ (def config - (assoc mem-node-config + (assoc api-stub/mem-node-config :blaze.interaction/update {:node (ig/ref :blaze.db/node) :executor (ig/ref :blaze.test/executor)} @@ -104,8 +104,8 @@ (defn- decode-more [more] (if (symbol? (first more)) - (into [(first more)] (tu/extract-txs-body (next more))) - (into [`config] (tu/extract-txs-body more)))) + (into [(first more)] (api-stub/extract-txs-body (next more))) + (into [`config] (api-stub/extract-txs-body more)))) (defmacro with-handler [[handler-binding & [node-binding]] & more] diff --git a/modules/interaction/test/blaze/interaction/util_spec.clj b/modules/interaction/test/blaze/interaction/util_spec.clj index 6489ed7a8..16875bab8 100644 --- a/modules/interaction/test/blaze/interaction/util_spec.clj +++ b/modules/interaction/test/blaze/interaction/util_spec.clj @@ -23,11 +23,6 @@ :ret :blaze.db.query/search-clauses) -(s/fdef iu/t - :args (s/cat :db :blaze.db/db) - :ret :blaze.db/t) - - (s/fdef iu/update-tx-op :args (s/cat :db :blaze.db/db :resource :blaze/resource :if-match (s/nilable string?) diff --git a/modules/interaction/test/blaze/interaction/util_test.clj b/modules/interaction/test/blaze/interaction/util_test.clj index 9e005a69f..f45d9a667 100644 --- a/modules/interaction/test/blaze/interaction/util_test.clj +++ b/modules/interaction/test/blaze/interaction/util_test.clj @@ -5,7 +5,8 @@ [blaze.db.tx-log.spec] [blaze.interaction.util :as iu] [blaze.interaction.util-spec] - [blaze.test-util :as tu :refer [satisfies-prop with-system]] + [blaze.module.test-util :refer [with-system]] + [blaze.test-util :as tu :refer [satisfies-prop]] [clojure.spec.test.alpha :as st] [clojure.string :as str] [clojure.test :as test :refer [are deftest is testing]] diff --git a/modules/jepsen/Makefile b/modules/jepsen/Makefile index 057e152a0..2674b09cc 100644 --- a/modules/jepsen/Makefile +++ b/modules/jepsen/Makefile @@ -14,6 +14,6 @@ register-test: prep clojure -M:register test --concurrency 16 --time-limit 60 -n localhost:8080 --delta-time 0.01 clean: - rm -rf .clj-kondo/.cache .cpcache target + rm -rf .clj-kondo/.cache .cpcache target store .PHONY: lint prep test test-coverage clean diff --git a/modules/jepsen/deps.edn b/modules/jepsen/deps.edn index ae39f52b8..b22083cb1 100644 --- a/modules/jepsen/deps.edn +++ b/modules/jepsen/deps.edn @@ -3,7 +3,7 @@ {:local/root "../fhir-client"} jepsen/jepsen - {:mvn/version "0.3.2"}} + {:mvn/version "0.3.3"}} :aliases {:test diff --git a/modules/kv/.clj-kondo/config.edn b/modules/kv/.clj-kondo/config.edn index 2a1202698..840014788 100644 --- a/modules/kv/.clj-kondo/config.edn +++ b/modules/kv/.clj-kondo/config.edn @@ -1,6 +1,6 @@ {:lint-as {blaze.db.kv.mem-test/with-system-data clojure.core/with-open - blaze.test-util/with-system clojure.core/with-open} + blaze.module.test-util/with-system clojure.core/with-open} :linters {:unsorted-required-namespaces diff --git a/modules/kv/deps.edn b/modules/kv/deps.edn index 1df99cb0c..b86086487 100644 --- a/modules/kv/deps.edn +++ b/modules/kv/deps.edn @@ -10,8 +10,8 @@ {:extra-paths ["test"] :extra-deps - {blaze/test-util - {:local/root "../test-util"}}} + {blaze/module-test-util + {:local/root "../module-test-util"}}} :kaocha {:extra-deps diff --git a/modules/kv/test/blaze/db/kv/mem_test.clj b/modules/kv/test/blaze/db/kv/mem_test.clj index 83cbdcc75..236c6ccb1 100644 --- a/modules/kv/test/blaze/db/kv/mem_test.clj +++ b/modules/kv/test/blaze/db/kv/mem_test.clj @@ -7,7 +7,8 @@ [blaze.db.kv.mem] [blaze.db.kv.mem-spec] [blaze.log] - [blaze.test-util :as tu :refer [bytes= given-thrown with-system]] + [blaze.module.test-util :refer [with-system]] + [blaze.test-util :as tu :refer [bytes= given-thrown]] [clojure.spec.alpha :as s] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [deftest is testing]] diff --git a/modules/luid/Makefile b/modules/luid/Makefile index 8eb60f27a..196a53ceb 100644 --- a/modules/luid/Makefile +++ b/modules/luid/Makefile @@ -1,16 +1,13 @@ lint: clj-kondo --lint src test deps.edn -prep: - clojure -X:deps prep - -test: prep +test: clojure -M:test:kaocha --profile :ci -test-coverage: prep +test-coverage: clojure -M:test:coverage clean: rm -rf .clj-kondo/.cache .cpcache target -.PHONY: lint prep test test-coverage clean +.PHONY: lint test test-coverage clean diff --git a/modules/luid/deps.edn b/modules/luid/deps.edn index d2039b3b1..2a9a2da75 100644 --- a/modules/luid/deps.edn +++ b/modules/luid/deps.edn @@ -1,10 +1,5 @@ {:deps - { - ;; TODO: only needed for prepping - blaze/fhir-structure - {:local/root "../fhir-structure"} - - blaze/module-base + {blaze/module-base {:local/root "../module-base"} blaze/spec diff --git a/modules/metrics/.clj-kondo/config.edn b/modules/metrics/.clj-kondo/config.edn index d12a895c1..a25d19101 100644 --- a/modules/metrics/.clj-kondo/config.edn +++ b/modules/metrics/.clj-kondo/config.edn @@ -1,5 +1,5 @@ {:lint-as - {blaze.test-util/with-system clojure.core/with-open} + {blaze.module.test-util/with-system clojure.core/with-open} :linters {:unsorted-required-namespaces diff --git a/modules/metrics/Makefile b/modules/metrics/Makefile index 8994a4b27..23d3127ff 100644 --- a/modules/metrics/Makefile +++ b/modules/metrics/Makefile @@ -1,10 +1,7 @@ lint: clj-kondo --lint src test deps.edn -prep: - clojure -X:deps prep - -build: prep +build: clojure -T:build compile test: build @@ -16,4 +13,4 @@ test-coverage: build clean: rm -rf .clj-kondo/.cache .cpcache target -.PHONY: lint prep build test test-coverage clean +.PHONY: lint build test test-coverage clean diff --git a/modules/metrics/deps.edn b/modules/metrics/deps.edn index 5bb316922..7e0bb8975 100644 --- a/modules/metrics/deps.edn +++ b/modules/metrics/deps.edn @@ -16,15 +16,15 @@ {:build {:deps {io.github.clojure/tools.build - {:git/tag "v0.9.4" :git/sha "76b78fe"}} + {:git/tag "v0.9.5" :git/sha "24f2894"}} :ns-default build} :test {:extra-paths ["test"] :extra-deps - {blaze/test-util - {:local/root "../test-util"}}} + {blaze/module-test-util + {:local/root "../module-test-util"}}} :kaocha {:extra-deps diff --git a/modules/metrics/test/blaze/metrics/handler_test.clj b/modules/metrics/test/blaze/metrics/handler_test.clj index c558d5a40..7ce549e5e 100644 --- a/modules/metrics/test/blaze/metrics/handler_test.clj +++ b/modules/metrics/test/blaze/metrics/handler_test.clj @@ -3,7 +3,8 @@ [blaze.metrics.handler] [blaze.metrics.registry] [blaze.metrics.spec :as spec] - [blaze.test-util :as tu :refer [given-thrown with-system]] + [blaze.module.test-util :refer [with-system]] + [blaze.test-util :as tu :refer [given-thrown]] [clojure.spec.alpha :as s] [clojure.spec.test.alpha :as st] [clojure.string :as str] diff --git a/modules/metrics/test/blaze/metrics/registry_test.clj b/modules/metrics/test/blaze/metrics/registry_test.clj index 50960b31a..6f1351d9d 100644 --- a/modules/metrics/test/blaze/metrics/registry_test.clj +++ b/modules/metrics/test/blaze/metrics/registry_test.clj @@ -2,7 +2,8 @@ (:require [blaze.metrics.core :as metrics] [blaze.metrics.registry] - [blaze.test-util :as tu :refer [given-thrown with-system]] + [blaze.module.test-util :refer [with-system]] + [blaze.test-util :as tu :refer [given-thrown]] [clojure.datafy :as datafy] [clojure.spec.alpha :as s] [clojure.spec.test.alpha :as st] @@ -20,12 +21,6 @@ (log/set-level! :trace) -(defn- fixture [f] - (st/instrument) - (f) - (st/unstrument)) - - (test/use-fixtures :each tu/fixture) diff --git a/modules/module-base/deps.edn b/modules/module-base/deps.edn index 7e4b78835..fd8854b0a 100644 --- a/modules/module-base/deps.edn +++ b/modules/module-base/deps.edn @@ -6,7 +6,7 @@ {:mvn/version "5.2.1"} com.google.guava/guava - {:mvn/version "32.1.0-jre" + {:mvn/version "32.1.2-jre" :exclusions [com.google.code.findbugs/jsr305 org.checkerframework/checker-qual diff --git a/modules/module-base/test/blaze/log_test.clj b/modules/module-base/test/blaze/log_test.clj new file mode 100644 index 000000000..8ec297fc8 --- /dev/null +++ b/modules/module-base/test/blaze/log_test.clj @@ -0,0 +1,10 @@ +(ns blaze.log-test + (:require + [blaze.log] + [clojure.test :refer [deftest is testing]] + [taoensso.timbre :as log])) + + +(deftest log-test + (testing "logging works" + (is (nil? (log/info "test"))))) diff --git a/modules/module-test-util/Makefile b/modules/module-test-util/Makefile new file mode 100644 index 000000000..c6dcaacb7 --- /dev/null +++ b/modules/module-test-util/Makefile @@ -0,0 +1,13 @@ +lint: + clj-kondo --lint src deps.edn + +test: + true + +test-coverage: + true + +clean: + rm -rf .clj-kondo/.cache .cpcache target + +.PHONY: lint test test-coverage clean diff --git a/modules/module-test-util/deps.edn b/modules/module-test-util/deps.edn new file mode 100644 index 000000000..3592d6dce --- /dev/null +++ b/modules/module-test-util/deps.edn @@ -0,0 +1,6 @@ +{:deps + {blaze/test-util + {:local/root "../test-util"} + + integrant/integrant + {:mvn/version "0.8.1"}}} diff --git a/modules/module-test-util/src/blaze/module/test_util.clj b/modules/module-test-util/src/blaze/module/test_util.clj new file mode 100644 index 000000000..b98f734fd --- /dev/null +++ b/modules/module-test-util/src/blaze/module/test_util.clj @@ -0,0 +1,15 @@ +(ns blaze.module.test-util + (:require + [integrant.core :as ig])) + + +(defmacro with-system + "Runs `body` inside a system that is initialized from `config`, bound to + `binding-form` and finally halted." + [[binding-form config] & body] + `(let [system# (ig/init ~config)] + (try + (let [~binding-form system#] + ~@body) + (finally + (ig/halt! system#))))) diff --git a/modules/openid-auth/.clj-kondo/config.edn b/modules/openid-auth/.clj-kondo/config.edn index d12a895c1..e2271fd78 100644 --- a/modules/openid-auth/.clj-kondo/config.edn +++ b/modules/openid-auth/.clj-kondo/config.edn @@ -1,5 +1,5 @@ {:lint-as - {blaze.test-util/with-system clojure.core/with-open} + {blaze.module.test-util/with-system clojure.core/with-open} :linters {:unsorted-required-namespaces @@ -15,6 +15,10 @@ {:level :warning} :warn-on-reflection - {:level :warning :warn-only-on-interop true}} + {:level :warning :warn-only-on-interop true} + + :consistent-alias + {:aliases + {blaze.scheduler sched}}} :skip-comments true} diff --git a/modules/openid-auth/Makefile b/modules/openid-auth/Makefile index 8eb60f27a..182928813 100644 --- a/modules/openid-auth/Makefile +++ b/modules/openid-auth/Makefile @@ -1,16 +1,19 @@ lint: clj-kondo --lint src test deps.edn -prep: - clojure -X:deps prep - -test: prep +test: clojure -M:test:kaocha --profile :ci -test-coverage: prep +test-coverage: clojure -M:test:coverage +deps-tree: + clojure -X:deps tree + +deps-list: + clojure -X:deps list + clean: rm -rf .clj-kondo/.cache .cpcache target -.PHONY: lint prep test test-coverage clean +.PHONY: lint test test-coverage deps-tree deps-list clean diff --git a/modules/openid-auth/deps.edn b/modules/openid-auth/deps.edn index 5a79e1877..92b256023 100644 --- a/modules/openid-auth/deps.edn +++ b/modules/openid-auth/deps.edn @@ -16,8 +16,8 @@ {:extra-paths ["test"] :extra-deps - {blaze/test-util - {:local/root "../test-util"} + {blaze/module-test-util + {:local/root "../module-test-util"} com.pgs-soft/HttpClientMock {:mvn/version "1.0.0"}}} diff --git a/modules/openid-auth/test/blaze/openid_auth_test.clj b/modules/openid-auth/test/blaze/openid_auth_test.clj index f74d1295b..35d9f07ea 100644 --- a/modules/openid-auth/test/blaze/openid_auth_test.clj +++ b/modules/openid-auth/test/blaze/openid_auth_test.clj @@ -1,8 +1,9 @@ (ns blaze.openid-auth-test (:require + [blaze.module.test-util :refer [with-system]] [blaze.openid-auth :as openid-auth] [blaze.openid-auth.spec] - [blaze.test-util :as tu :refer [given-thrown with-system]] + [blaze.test-util :as tu :refer [given-thrown]] [buddy.auth.protocols :as p] [clojure.spec.alpha :as s] [clojure.spec.test.alpha :as st] diff --git a/modules/operation-graphql/.clj-kondo/config.edn b/modules/operation-graphql/.clj-kondo/config.edn index 4fdb72f2e..67cf86049 100644 --- a/modules/operation-graphql/.clj-kondo/config.edn +++ b/modules/operation-graphql/.clj-kondo/config.edn @@ -1,7 +1,7 @@ {:lint-as {blaze.anomaly/when-ok clojure.core/let blaze.fhir.operation.graphql-test/with-handler clojure.core/fn - blaze.test-util/with-system clojure.core/with-open} + blaze.module.test-util/with-system clojure.core/with-open} :linters {:unsorted-required-namespaces @@ -22,6 +22,7 @@ :consistent-alias {:aliases {blaze.db.api d + cognitect.anomalies anom ring.util.response ring}}} :skip-comments true} diff --git a/modules/operation-graphql/test/blaze/fhir/operation/graphql_test.clj b/modules/operation-graphql/test/blaze/fhir/operation/graphql_test.clj index ac566384d..c24dbf657 100644 --- a/modules/operation-graphql/test/blaze/fhir/operation/graphql_test.clj +++ b/modules/operation-graphql/test/blaze/fhir/operation/graphql_test.clj @@ -1,7 +1,7 @@ (ns blaze.fhir.operation.graphql-test (:require [blaze.async.comp :as ac] - [blaze.db.api-stub :refer [mem-node-config with-system-data]] + [blaze.db.api-stub :as api-stub :refer [with-system-data]] [blaze.db.resource-store :as rs] [blaze.executors :as ex] [blaze.fhir.operation.graphql :as graphql] @@ -9,7 +9,8 @@ [blaze.log] [blaze.middleware.fhir.db :refer [wrap-db]] [blaze.middleware.fhir.db-spec] - [blaze.test-util :as tu :refer [given-thrown with-system]] + [blaze.module.test-util :refer [with-system]] + [blaze.test-util :as tu :refer [given-thrown]] [clojure.spec.alpha :as s] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [deftest is testing]] @@ -69,7 +70,7 @@ (def config - (assoc mem-node-config + (assoc api-stub/mem-node-config ::graphql/handler {:node (ig/ref :blaze.db/node) :executor (ig/ref :blaze.test/executor)} @@ -77,7 +78,7 @@ (defmacro with-handler [[handler-binding] & more] - (let [[txs body] (tu/extract-txs-body more)] + (let [[txs body] (api-stub/extract-txs-body more)] `(with-system-data [{node# :blaze.db/node handler# ::graphql/handler} config] ~txs diff --git a/modules/operation-measure-evaluate-measure/.clj-kondo/config.edn b/modules/operation-measure-evaluate-measure/.clj-kondo/config.edn index a96f70378..2acbb21c8 100644 --- a/modules/operation-measure-evaluate-measure/.clj-kondo/config.edn +++ b/modules/operation-measure-evaluate-measure/.clj-kondo/config.edn @@ -3,7 +3,7 @@ blaze.anomaly/when-ok clojure.core/let blaze.db.api-stub/with-system-data clojure.core/with-open blaze.fhir.operation.evaluate-measure-test/with-handler clojure.core/fn - blaze.test-util/with-system clojure.core/with-open + blaze.module.test-util/with-system clojure.core/with-open prometheus.alpha/defcounter clojure.core/def prometheus.alpha/defhistogram clojure.core/def} @@ -26,6 +26,9 @@ :consistent-alias {:aliases {blaze.db.api d + blaze.elm.compiler.external-data ed + blaze.elm.expression expr + cognitect.anomalies anom ring.util.response ring}}} :skip-comments true} diff --git a/modules/operation-measure-evaluate-measure/src/blaze/fhir/operation/evaluate_measure/cql.clj b/modules/operation-measure-evaluate-measure/src/blaze/fhir/operation/evaluate_measure/cql.clj index f065e82f1..2030bbc84 100644 --- a/modules/operation-measure-evaluate-measure/src/blaze/fhir/operation/evaluate_measure/cql.clj +++ b/modules/operation-measure-evaluate-measure/src/blaze/fhir/operation/evaluate_measure/cql.clj @@ -2,6 +2,7 @@ (:require [blaze.anomaly :as ba :refer [if-ok when-ok]] [blaze.db.api :as d] + [blaze.elm.compiler.external-data :as ed] [blaze.elm.expression :as expr] [blaze.elm.util :as elm-util] [blaze.fhir.spec :as fhir-spec] @@ -40,9 +41,9 @@ (ex-message e))) -(defn- evaluate-expression-1* [context subject-handle name expression] +(defn- evaluate-expression-1* [context subject name expression] (try - (expr/eval context expression subject-handle) + (expr/eval context expression subject) (catch Exception e (let [ex-data (ex-data e)] ;; only log if the exception hasn't ex-data because exception with @@ -67,12 +68,12 @@ (defn- evaluate-expression-1 - [{:keys [timeout-eclipsed?] :as context} subject-handle name expression] + [{:keys [timeout-eclipsed?] :as context} subject name expression] (if (timeout-eclipsed?) {::anom/category ::anom/interrupted ::anom/message (timeout-eclipsed-msg context) :timeout (:timeout context)} - (evaluate-expression-1* context subject-handle name expression))) + (evaluate-expression-1* context subject name expression))) (defn- close-batch-db! [{:keys [db]}] @@ -140,43 +141,47 @@ (expression-combine-sum-op context))) -(defn- handle [subject-handle] - {:population-handle subject-handle :subject-handle subject-handle}) +(defn- handle [subject] + {:population-handle subject :subject-handle subject}) -(defn- conj-all! [handles subject-handle population-handles] +(defn- conj-all! [resources subject population-resources] (reduce - (fn [handles population-handle] - (conj! handles {:population-handle population-handle - :subject-handle subject-handle})) - handles - population-handles)) + (fn [resources population-resource] + (conj! resources {:population-handle population-resource + :subject-handle subject})) + resources + population-resources)) (defn- expression-reduce-subject-based-conj-op [{:keys [name expression]}] - (fn [context subject-handle] - (if-ok [res (evaluate-expression-1 context subject-handle name expression)] - (cond-> context res (update ::result conj! (handle subject-handle))) - #(reduced (assoc context ::result %))))) + (fn [{:keys [db] :as context} subject-handle] + (let [subject (ed/mk-resource db subject-handle)] + (if-ok [res (evaluate-expression-1 context subject name expression)] + (cond-> context res (update ::result conj! (handle subject))) + #(reduced (assoc context ::result %)))))) (defn- expression-reduce-conj-op [{:keys [name expression]}] - (fn [context subject-handle] - (if-ok [res (evaluate-expression-1 context subject-handle name expression)] - (update context ::result conj-all! subject-handle res) - #(reduced (assoc context ::result %))))) + (fn [{:keys [db] :as context} subject-handle] + (let [subject (ed/mk-resource db subject-handle)] + (if-ok [res (evaluate-expression-1 context subject name expression)] + (update context ::result conj-all! subject res) + #(reduced (assoc context ::result %)))))) (defn- expression-reduce-subject-based-sum-op [{:keys [name expression]}] - (fn [context subject-handle] - (if-ok [res (evaluate-expression-1 context subject-handle name expression)] + (fn [{:keys [db] :as context} subject-handle] + (if-ok [res (evaluate-expression-1 context (ed/mk-resource db subject-handle) + name expression)] (cond-> context res (update ::result inc)) #(reduced (assoc context ::result %))))) (defn- expression-reduce-sum-op [{:keys [name expression]}] - (fn [context subject-handle] - (if-ok [res (evaluate-expression-1 context subject-handle name expression)] + (fn [{:keys [db] :as context} subject-handle] + (if-ok [res (evaluate-expression-1 context (ed/mk-resource db subject-handle) + name expression)] (update context ::result + (count res)) #(reduced (assoc context ::result %))))) @@ -294,13 +299,12 @@ (defn evaluate-individual-expression - "Evaluates the expression with `name` on `subject-handle` according to - `context`. + "Evaluates the expression with `name` on `subject` according to `context`. Returns an anomaly in case of errors." - [context subject-handle name] + [context subject name] (when-ok [{:keys [name expression]} (expression-def context name)] - (evaluate-expression-1 context subject-handle name expression))) + (evaluate-expression-1 context subject name expression))) (defn- stratum-result-reduce-op [result stratum subject-handle] diff --git a/modules/operation-measure-evaluate-measure/src/blaze/fhir/operation/evaluate_measure/measure.clj b/modules/operation-measure-evaluate-measure/src/blaze/fhir/operation/evaluate_measure/measure.clj index 87caab235..62cea1e41 100644 --- a/modules/operation-measure-evaluate-measure/src/blaze/fhir/operation/evaluate_measure/measure.clj +++ b/modules/operation-measure-evaluate-measure/src/blaze/fhir/operation/evaluate_measure/measure.clj @@ -4,6 +4,7 @@ [blaze.coll.core :as coll] [blaze.cql-translator :as cql-translator] [blaze.db.api :as d] + [blaze.elm.compiler.external-data :as ed] [blaze.elm.compiler.library :as library] [blaze.fhir.operation.evaluate-measure.measure.population :as population] [blaze.fhir.operation.evaluate-measure.measure.stratifier :as stratifier] @@ -317,7 +318,7 @@ (if-let [{:keys [op] :as handle} (d/resource-handle db type id)] (if (identical? :delete op) (ba/incorrect (missing-subject-msg type id)) - handle) + (ed/mk-resource db handle)) (ba/incorrect (missing-subject-msg type id)))) diff --git a/modules/operation-measure-evaluate-measure/src/blaze/fhir/operation/evaluate_measure/measure/spec.clj b/modules/operation-measure-evaluate-measure/src/blaze/fhir/operation/evaluate_measure/measure/spec.clj index 9a4bc8eec..268878f28 100644 --- a/modules/operation-measure-evaluate-measure/src/blaze/fhir/operation/evaluate_measure/measure/spec.clj +++ b/modules/operation-measure-evaluate-measure/src/blaze/fhir/operation/evaluate_measure/measure/spec.clj @@ -1,6 +1,7 @@ (ns blaze.fhir.operation.evaluate-measure.measure.spec (:require [blaze.db.spec] + [blaze.elm.compiler.external-data :as ed] [blaze.fhir.operation.evaluate-measure.measure :as-alias measure] [blaze.fhir.spec.spec] [clojure.spec.alpha :as s])) @@ -16,11 +17,11 @@ (s/def ::measure/population-handle - :blaze.db/resource-handle) + ed/resource?) (s/def ::measure/subject-handle - :blaze.db/resource-handle) + ed/resource?) (s/def ::measure/handle diff --git a/modules/operation-measure-evaluate-measure/src/blaze/fhir/operation/evaluate_measure/measure/util.clj b/modules/operation-measure-evaluate-measure/src/blaze/fhir/operation/evaluate_measure/measure/util.clj index d48286426..203197663 100644 --- a/modules/operation-measure-evaluate-measure/src/blaze/fhir/operation/evaluate_measure/measure/util.clj +++ b/modules/operation-measure-evaluate-measure/src/blaze/fhir/operation/evaluate_measure/measure/util.clj @@ -1,7 +1,6 @@ (ns blaze.fhir.operation.evaluate-measure.measure.util (:require [blaze.anomaly :as ba] - [blaze.db.impl.index.resource-handle :as rh] [blaze.fhir.spec.type :as type])) @@ -35,8 +34,8 @@ (type/map->Reference {:reference (str "List/" list-id)})) -(defn- resource-handle-reference [resource-handle] - (type/map->Reference {:reference (rh/reference resource-handle)})) +(defn- resource-reference [{:keys [id] :as resource}] + (type/map->Reference {:reference (str (name (type/type resource)) "/" id)})) (defn- population-tx-ops [list-id handles] @@ -49,7 +48,7 @@ (mapv (fn [{:keys [population-handle]}] {:fhir/type :fhir.List/entry - :item (resource-handle-reference population-handle)}) + :item (resource-reference population-handle)}) handles)}]]) diff --git a/modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/cql_spec.clj b/modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/cql_spec.clj index fd0b6e8aa..6ea9e2fed 100644 --- a/modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/cql_spec.clj +++ b/modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/cql_spec.clj @@ -1,6 +1,8 @@ (ns blaze.fhir.operation.evaluate-measure.cql-spec (:require [blaze.db.spec] + [blaze.elm.compiler.external-data :as ed] + [blaze.elm.compiler.external-data-spec] [blaze.elm.compiler.library-spec] [blaze.elm.expression-spec] [blaze.fhir.operation.evaluate-measure.cql :as cql] @@ -23,7 +25,7 @@ (s/fdef cql/evaluate-individual-expression :args (s/cat :context ::cql/evaluate-individual-expression-context - :subject-handle :blaze.db/resource-handle + :subject ed/resource? :name string?) :ret (s/or :value any? :anomaly ::anom/anomaly)) diff --git a/modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/cql_test.clj b/modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/cql_test.clj index 969e08f40..feba245fb 100644 --- a/modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/cql_test.clj +++ b/modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/cql_test.clj @@ -9,9 +9,11 @@ [blaze.elm.expression :as expr] [blaze.fhir.operation.evaluate-measure.cql :as cql] [blaze.fhir.operation.evaluate-measure.cql-spec] + [blaze.fhir.operation.evaluate-measure.test-util :as em-tu] [blaze.fhir.spec :as fhir-spec] [blaze.fhir.spec.type] - [blaze.test-util :as tu :refer [with-system]] + [blaze.module.test-util :refer [with-system]] + [blaze.test-util :as tu] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [deftest is testing]] [cognitect.anomalies :as anom] @@ -183,7 +185,7 @@ :expression-context := "Patient"))))) (testing "population basis doesn't match the expression return type" - (testing "boolean" + (testing "Boolean" (with-system [system mem-node-config] (let [context (context system library-encounter)] (doseq [return-handles? [true false] @@ -236,21 +238,21 @@ (with-system-data [system mem-node-config] [[[:put {:fhir/type :fhir/Patient :id "0" :gender #fhir/code"male"}]]] (let [{:keys [db] :as context} (context system library-gender) - patient (d/resource-handle db "Patient" "0")] + patient (em-tu/resource db "Patient" "0")] (is (true? (cql/evaluate-individual-expression context patient "InInitialPopulation")))))) (testing "no match" (with-system-data [system mem-node-config] [[[:put {:fhir/type :fhir/Patient :id "0"}]]] (let [{:keys [db] :as context} (context system library-gender) - patient (d/resource-handle db "Patient" "0")] + patient (em-tu/resource db "Patient" "0")] (is (nil? (cql/evaluate-individual-expression context patient "InInitialPopulation")))))) (testing "missing expression" (with-system-data [system mem-node-config] [[[:put {:fhir/type :fhir/Patient :id "0"}]]] (let [{:keys [db] :as context} (context system library-empty) - patient (d/resource-handle db "Patient" "0")] + patient (em-tu/resource db "Patient" "0")] (given (cql/evaluate-individual-expression context patient "InInitialPopulation") ::anom/category := ::anom/incorrect ::anom/message := "Missing expression with name `InInitialPopulation`." @@ -261,7 +263,7 @@ [[[:put {:fhir/type :fhir/Patient :id "0"}]]] (let [{:keys [db] :as context} (assoc (context system library-error) :parameters {"Numbers" [1 2]}) - patient (d/resource-handle db "Patient" "0")] + patient (em-tu/resource db "Patient" "0")] (given (cql/evaluate-individual-expression context patient "InInitialPopulation") ::anom/category := ::anom/conflict ::anom/message := "More than one element in `SingletonFrom` expression." @@ -274,10 +276,6 @@ (fn [_ _ _] ["1" "2"])) -(defn- handle [subject-handle] - {:population-handle subject-handle :subject-handle subject-handle}) - - (deftest calc-strata-test (testing "missing expression" (with-system [system mem-node-config] @@ -291,9 +289,10 @@ (with-system-data [system mem-node-config] [[[:put {:fhir/type :fhir/Patient :id "0"}]]] - (let [{:keys [db] :as context} (context system library-gender)] + (let [{:keys [db] :as context} (context system library-gender) + handles (into [] (em-tu/handle-mapper db) (d/type-list db "Patient"))] (with-redefs [expr/eval (failing-eval "msg-221825")] - (given (cql/calc-strata context "Gender" (mapv handle (d/type-list db "Patient"))) + (given (cql/calc-strata context "Gender" handles) ::anom/category := ::anom/fault ::anom/message := "Error while evaluating the expression `Gender`: msg-221825"))))) @@ -301,9 +300,10 @@ (with-system-data [system mem-node-config] [[[:put {:fhir/type :fhir/Patient :id "0"}]]] - (let [{:keys [db] :as context} (context system library-gender)] + (let [{:keys [db] :as context} (context system library-gender) + handles (into [] (em-tu/handle-mapper db) (d/type-list db "Patient"))] (with-redefs [expr/eval two-value-eval] - (given (cql/calc-strata context "Gender" (mapv handle (d/type-list db "Patient"))) + (given (cql/calc-strata context "Gender" handles) ::anom/category := ::anom/incorrect ::anom/message := "CQL expression `Gender` returned more than one value for resource `Patient/0`."))))) @@ -311,8 +311,9 @@ (with-system-data [system mem-node-config] [[[:put {:fhir/type :fhir/Patient :id "0"}]]] - (let [{:keys [db] :as context} (assoc (context system library-gender) :timeout-eclipsed? (constantly true))] - (given (cql/calc-strata context "Gender" (mapv handle (d/type-list db "Patient"))) + (let [{:keys [db] :as context} (assoc (context system library-gender) :timeout-eclipsed? (constantly true)) + handles (into [] (em-tu/handle-mapper db) (d/type-list db "Patient"))] + (given (cql/calc-strata context "Gender" handles) ::anom/category := ::anom/interrupted ::anom/message := "Timeout of 42000 millis eclipsed while evaluating.")))) @@ -324,7 +325,8 @@ [:put {:fhir/type :fhir/Patient :id "3" :gender #fhir/code"male"}]]] (let [{:keys [db] :as context} (context system library-gender) - result (cql/calc-strata context "Gender" (mapv handle (d/type-list db "Patient")))] + handles (into [] (em-tu/handle-mapper db) (d/type-list db "Patient")) + result (cql/calc-strata context "Gender" handles)] (testing "contains a nil entry for the patient with id 0" (given (result nil) @@ -367,14 +369,14 @@ (let [{:keys [db] :as context} (context system library-encounter-status) handles - [{:population-handle (d/resource-handle db "Encounter" "0") - :subject-handle (d/resource-handle db "Patient" "0")} - {:population-handle (d/resource-handle db "Encounter" "1") - :subject-handle (d/resource-handle db "Patient" "0")} - {:population-handle (d/resource-handle db "Encounter" "2") - :subject-handle (d/resource-handle db "Patient" "1")} - {:population-handle (d/resource-handle db "Encounter" "3") - :subject-handle (d/resource-handle db "Patient" "2")}] + [{:population-handle (em-tu/resource db "Encounter" "0") + :subject-handle (em-tu/resource db "Patient" "0")} + {:population-handle (em-tu/resource db "Encounter" "1") + :subject-handle (em-tu/resource db "Patient" "0")} + {:population-handle (em-tu/resource db "Encounter" "2") + :subject-handle (em-tu/resource db "Patient" "1")} + {:population-handle (em-tu/resource db "Encounter" "3") + :subject-handle (em-tu/resource db "Patient" "2")}] result (cql/calc-function-strata context "Status" handles)] (testing "contains a nil entry for the encounter with id 0" @@ -408,9 +410,10 @@ (testing "failing eval" (with-system-data [system mem-node-config] [[[:put {:fhir/type :fhir/Patient :id "0"}]]] - (let [{:keys [db] :as context} (context system library-encounter-status)] + (let [{:keys [db] :as context} (context system library-encounter-status) + handles (into [] (em-tu/handle-mapper db) (d/type-list db "Patient"))] (with-redefs [expr/eval (failing-eval "msg-111807")] - (given (cql/calc-function-strata context "Status" (mapv handle (d/type-list db "Patient"))) + (given (cql/calc-function-strata context "Status" handles) ::anom/category := ::anom/fault ::anom/message := "Error while evaluating the expression `Status`: msg-111807")))))) @@ -419,8 +422,9 @@ (testing "failing eval" (with-system-data [system mem-node-config] [[[:put {:fhir/type :fhir/Patient :id "0"}]]] - (let [{:keys [db] :as context} (context system library-gender)] + (let [{:keys [db] :as context} (context system library-gender) + handles (into [] (em-tu/handle-mapper db) (d/type-list db "Patient"))] (with-redefs [expr/eval (failing-eval "msg-111557")] - (given (cql/calc-multi-component-strata context ["Gender"] (mapv handle (d/type-list db "Patient"))) + (given (cql/calc-multi-component-strata context ["Gender"] handles) ::anom/category := ::anom/fault ::anom/message := "Error while evaluating the expression `Gender`: msg-111557")))))) diff --git a/modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/measure/population/spec.clj b/modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/measure/population/spec.clj index 4fb89d24e..8c749ed31 100644 --- a/modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/measure/population/spec.clj +++ b/modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/measure/population/spec.clj @@ -1,6 +1,7 @@ (ns blaze.fhir.operation.evaluate-measure.measure.population.spec (:require [blaze.db.spec] + [blaze.elm.compiler.external-data :as ed] [blaze.fhir.operation.evaluate-measure.cql :as-alias cql] [blaze.fhir.operation.evaluate-measure.cql.spec] [blaze.fhir.operation.evaluate-measure.measure.population :as-alias population] @@ -13,9 +14,10 @@ (s/def ::population/subject-handle - :blaze.db/resource-handle) + ed/resource?) (s/def ::population/context - (s/merge ::cql/context - (s/keys :req-un [(or ::population/subject-type ::population/subject-handle)]))) + (s/merge + ::cql/context + (s/keys :req-un [(or ::population/subject-type ::population/subject-handle)]))) diff --git a/modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/measure/stratifier/spec.clj b/modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/measure/stratifier/spec.clj index 07dfdd78e..1d1893a26 100644 --- a/modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/measure/stratifier/spec.clj +++ b/modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/measure/stratifier/spec.clj @@ -12,7 +12,7 @@ (s/def ::stratifier/evaluated-populations - (s/keys :req-un [::handles])) + (s/keys :req-un [::stratifier/handles])) (s/def ::stratifier/context diff --git a/modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/measure/stratifier_test.clj b/modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/measure/stratifier_test.clj index e3cafa431..bedf1dc60 100644 --- a/modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/measure/stratifier_test.clj +++ b/modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/measure/stratifier_test.clj @@ -8,7 +8,9 @@ [blaze.elm.compiler.library :as library] [blaze.fhir.operation.evaluate-measure.measure.stratifier :as stratifier] [blaze.fhir.operation.evaluate-measure.measure.stratifier-spec] - [blaze.test-util :as tu :refer [with-system]] + [blaze.fhir.operation.evaluate-measure.test-util :as em-tu] + [blaze.module.test-util :refer [with-system]] + [blaze.test-util :as tu] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [deftest testing]] [cognitect.anomalies :as anom] @@ -180,10 +182,6 @@ :function-defs function-defs})) -(defn- handle [subject-handle] - {:population-handle subject-handle :subject-handle subject-handle}) - - (deftest evaluate (testing "one component" (testing "gender" @@ -194,7 +192,8 @@ [:put {:fhir/type :fhir/Patient :id "3" :gender #fhir/code"male"}]]] (let [{:keys [db] :as context} (context system library-age-gender) - evaluated-populations {:handles [(mapv handle (d/type-list db "Patient"))]}] + handles (into [] (em-tu/handle-mapper db) (d/type-list db "Patient")) + evaluated-populations {:handles [handles]}] (testing "report-type population" (given (stratifier/evaluate (assoc context :report-type "population") @@ -248,8 +247,8 @@ (let [{:keys [db] :as context} (context system library-observation-code) evaluated-populations {:handles - [[{:population-handle (d/resource-handle db "Observation" "0") - :subject-handle (d/resource-handle db "Patient" "0")}]]}] + [[{:population-handle (em-tu/resource db "Observation" "0") + :subject-handle (em-tu/resource db "Patient" "0")}]]}] (testing "report-type population" (given (stratifier/evaluate @@ -278,10 +277,10 @@ (let [{:keys [db] :as context} (context system library-observation-value-age) evaluated-populations {:handles - [[{:population-handle (d/resource-handle db "Observation" "0") - :subject-handle (d/resource-handle db "Patient" "0")} - {:population-handle (d/resource-handle db "Observation" "1") - :subject-handle (d/resource-handle db "Patient" "0")}]]}] + [[{:population-handle (em-tu/resource db "Observation" "0") + :subject-handle (em-tu/resource db "Patient" "0")} + {:population-handle (em-tu/resource db "Observation" "1") + :subject-handle (em-tu/resource db "Patient" "0")}]]}] (testing "report-type population" (given (stratifier/evaluate @@ -333,7 +332,8 @@ [[[:put {:fhir/type :fhir/Patient :id "0"}]]] (let [{:keys [db] :as context} (context system library-age-gender) - evaluated-populations {:handles [(mapv handle (d/type-list db "Patient"))]}] + handles (into [] (em-tu/handle-mapper db) (d/type-list db "Patient")) + evaluated-populations {:handles [handles]}] (given (stratifier/evaluate (assoc context :report-type "population" @@ -356,7 +356,8 @@ :gender #fhir/code"male" :birthDate #fhir/date"1950"}]]] (let [{:keys [db] :as context} (context system library-age-gender) - evaluated-populations {:handles [(mapv handle (d/type-list db "Patient"))]}] + handles (into [] (em-tu/handle-mapper db) (d/type-list db "Patient")) + evaluated-populations {:handles [handles]}] (testing "report-type population" (given (stratifier/evaluate (assoc context :report-type "population") @@ -401,14 +402,14 @@ (let [{:keys [db] :as context} (context system library-encounter-status-age) evaluated-populations {:handles - [[{:population-handle (d/resource-handle db "Encounter" "0") - :subject-handle (d/resource-handle db "Patient" "0")} - {:population-handle (d/resource-handle db "Encounter" "1") - :subject-handle (d/resource-handle db "Patient" "0")} - {:population-handle (d/resource-handle db "Encounter" "2") - :subject-handle (d/resource-handle db "Patient" "1")} - {:population-handle (d/resource-handle db "Encounter" "3") - :subject-handle (d/resource-handle db "Patient" "2")}]]}] + [[{:population-handle (em-tu/resource db "Encounter" "0") + :subject-handle (em-tu/resource db "Patient" "0")} + {:population-handle (em-tu/resource db "Encounter" "1") + :subject-handle (em-tu/resource db "Patient" "0")} + {:population-handle (em-tu/resource db "Encounter" "2") + :subject-handle (em-tu/resource db "Patient" "1")} + {:population-handle (em-tu/resource db "Encounter" "3") + :subject-handle (em-tu/resource db "Patient" "2")}]]}] (testing "report-type population" (given (stratifier/evaluate @@ -451,10 +452,10 @@ (let [{:keys [db] :as context} (context system library-observation-value-age) evaluated-populations {:handles - [[{:population-handle (d/resource-handle db "Observation" "0") - :subject-handle (d/resource-handle db "Patient" "0")} - {:population-handle (d/resource-handle db "Observation" "1") - :subject-handle (d/resource-handle db "Patient" "0")}]]}] + [[{:population-handle (em-tu/resource db "Observation" "0") + :subject-handle (em-tu/resource db "Patient" "0")} + {:population-handle (em-tu/resource db "Observation" "1") + :subject-handle (em-tu/resource db "Patient" "0")}]]}] (testing "report-type population" (given (stratifier/evaluate diff --git a/modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/test_util.clj b/modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/test_util.clj index e5dd5ed68..38c852436 100644 --- a/modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/test_util.clj +++ b/modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure/test_util.clj @@ -1,6 +1,9 @@ (ns blaze.fhir.operation.evaluate-measure.test-util (:require [blaze.async.comp :as ac] + [blaze.db.api :as d] + [blaze.elm.compiler.external-data :as ed] + [blaze.elm.compiler.external-data-spec] [blaze.handler.util :as handler-util])) @@ -8,3 +11,15 @@ (fn [request] (-> (handler request) (ac/exceptionally handler-util/error-response)))) + + +(defn- handle [subject-handle] + {:population-handle subject-handle :subject-handle subject-handle}) + + +(defn handle-mapper [db] + (comp (ed/resource-mapper db) (map handle))) + + +(defn resource [db type id] + (ed/mk-resource db (d/resource-handle db type id))) diff --git a/modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure_test.clj b/modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure_test.clj index b92da4658..30b741b5b 100644 --- a/modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure_test.clj +++ b/modules/operation-measure-evaluate-measure/test/blaze/fhir/operation/evaluate_measure_test.clj @@ -2,7 +2,7 @@ (:require [blaze.anomaly-spec] [blaze.async.comp :as ac] - [blaze.db.api-stub :refer [mem-node-config with-system-data]] + [blaze.db.api-stub :as api-stub :refer [with-system-data]] [blaze.db.resource-store :as rs] [blaze.executors :as ex] [blaze.fhir.operation.evaluate-measure :as evaluate-measure] @@ -11,7 +11,8 @@ [blaze.metrics.spec] [blaze.middleware.fhir.db :refer [wrap-db]] [blaze.middleware.fhir.db-spec] - [blaze.test-util :as tu :refer [given-thrown with-system]] + [blaze.module.test-util :refer [with-system]] + [blaze.test-util :as tu :refer [given-thrown]] [clojure.spec.alpha :as s] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [deftest is testing]] @@ -157,7 +158,7 @@ (def config - (assoc mem-node-config + (assoc api-stub/mem-node-config ::evaluate-measure/handler {:node (ig/ref :blaze.db/node) :executor (ig/ref :blaze.test/executor) @@ -176,7 +177,7 @@ (defmacro with-handler [[handler-binding] & more] - (let [[txs body] (tu/extract-txs-body more)] + (let [[txs body] (api-stub/extract-txs-body more)] `(with-system-data [{node# :blaze.db/node handler# ::evaluate-measure/handler} config] ~txs diff --git a/modules/operation-patient-everything/test/blaze/operation/patient/everything_test.clj b/modules/operation-patient-everything/test/blaze/operation/patient/everything_test.clj index 3a66f5a0a..90485008a 100644 --- a/modules/operation-patient-everything/test/blaze/operation/patient/everything_test.clj +++ b/modules/operation-patient-everything/test/blaze/operation/patient/everything_test.clj @@ -1,7 +1,7 @@ (ns blaze.operation.patient.everything-test (:require [blaze.async.comp :as ac] - [blaze.db.api-stub :refer [mem-node-config with-system-data]] + [blaze.db.api-stub :as api-stub :refer [with-system-data]] [blaze.fhir.spec :as fhir-spec] [blaze.handler.util :as handler-util] [blaze.middleware.fhir.db :as db] @@ -62,7 +62,7 @@ (def config - (assoc mem-node-config + (assoc api-stub/mem-node-config :blaze.operation.patient/everything {:clock (ig/ref :blaze.test/fixed-clock) :rng-fn (ig/ref :blaze.test/fixed-rng-fn)} @@ -84,7 +84,7 @@ (defmacro with-handler [[handler-binding & [node-binding]] & more] - (let [[txs body] (tu/extract-txs-body more)] + (let [[txs body] (api-stub/extract-txs-body more)] `(with-system-data [{node# :blaze.db/node handler# :blaze.operation.patient/everything} config] ~txs diff --git a/modules/page-store-cassandra/.clj-kondo/config.edn b/modules/page-store-cassandra/.clj-kondo/config.edn index 71fcc5ee5..d6d5d9157 100644 --- a/modules/page-store-cassandra/.clj-kondo/config.edn +++ b/modules/page-store-cassandra/.clj-kondo/config.edn @@ -1,6 +1,6 @@ {:lint-as {blaze.anomaly/when-ok clojure.core/let - blaze.test-util/with-system clojure.core/with-open + blaze.module.test-util/with-system clojure.core/with-open prometheus.alpha/defhistogram clojure.core/def} :linters @@ -17,6 +17,10 @@ {:level :warning} :warn-on-reflection - {:level :warning :warn-only-on-interop true}} + {:level :warning :warn-only-on-interop true} + + :consistent-alias + {:aliases + {cognitect.anomalies anom}}} :skip-comments true} diff --git a/modules/page-store-cassandra/deps.edn b/modules/page-store-cassandra/deps.edn index bf51356c1..a54435e41 100644 --- a/modules/page-store-cassandra/deps.edn +++ b/modules/page-store-cassandra/deps.edn @@ -19,8 +19,8 @@ {:extra-paths ["test"] :extra-deps - {blaze/test-util - {:local/root "../test-util"}}} + {blaze/fhir-test-util + {:local/root "../fhir-test-util"}}} :kaocha {:extra-deps diff --git a/modules/page-store-cassandra/test/blaze/page_store/cassandra_test.clj b/modules/page-store-cassandra/test/blaze/page_store/cassandra_test.clj index 73f196bb7..820e98313 100644 --- a/modules/page-store-cassandra/test/blaze/page_store/cassandra_test.clj +++ b/modules/page-store-cassandra/test/blaze/page_store/cassandra_test.clj @@ -4,12 +4,14 @@ [blaze.byte-buffer :as bb] [blaze.cassandra :as cass] [blaze.cassandra-spec] + [blaze.fhir.test-util] + [blaze.module.test-util :refer [with-system]] [blaze.page-store :as page-store] [blaze.page-store.cassandra] [blaze.page-store.cassandra.codec :as codec] [blaze.page-store.cassandra.codec-spec] [blaze.page-store.cassandra.statement :as statement] - [blaze.test-util :as tu :refer [given-thrown with-system]] + [blaze.test-util :as tu :refer [given-thrown]] [clojure.spec.alpha :as s] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [deftest is testing]] diff --git a/modules/page-store/.clj-kondo/config.edn b/modules/page-store/.clj-kondo/config.edn index d12a895c1..a25d19101 100644 --- a/modules/page-store/.clj-kondo/config.edn +++ b/modules/page-store/.clj-kondo/config.edn @@ -1,5 +1,5 @@ {:lint-as - {blaze.test-util/with-system clojure.core/with-open} + {blaze.module.test-util/with-system clojure.core/with-open} :linters {:unsorted-required-namespaces diff --git a/modules/page-store/Makefile b/modules/page-store/Makefile index 8eb60f27a..7510b665c 100644 --- a/modules/page-store/Makefile +++ b/modules/page-store/Makefile @@ -10,7 +10,13 @@ test: prep test-coverage: prep clojure -M:test:coverage +deps-tree: + clojure -X:deps tree + +deps-list: + clojure -X:deps list + clean: rm -rf .clj-kondo/.cache .cpcache target -.PHONY: lint prep test test-coverage clean +.PHONY: lint prep test test-coverage deps-tree deps-list clean diff --git a/modules/page-store/deps.edn b/modules/page-store/deps.edn index 53463d0f6..640a37d08 100644 --- a/modules/page-store/deps.edn +++ b/modules/page-store/deps.edn @@ -8,18 +8,15 @@ {:local/root "../db"} blaze/module-base - {:local/root "../module-base"} - - com.github.ben-manes.caffeine/caffeine - {:mvn/version "3.1.6"}} + {:local/root "../module-base"}} :aliases {:test {:extra-paths ["test"] :extra-deps - {blaze/test-util - {:local/root "../test-util"}}} + {blaze/fhir-test-util + {:local/root "../fhir-test-util"}}} :kaocha {:extra-deps diff --git a/modules/page-store/test/blaze/page_store/local_test.clj b/modules/page-store/test/blaze/page_store/local_test.clj index d48091f77..4b7e1c056 100644 --- a/modules/page-store/test/blaze/page_store/local_test.clj +++ b/modules/page-store/test/blaze/page_store/local_test.clj @@ -1,13 +1,15 @@ (ns blaze.page-store.local-test (:require [blaze.anomaly-spec] + [blaze.fhir.test-util :refer [given-failed-future]] [blaze.metrics.core :as metrics] [blaze.metrics.spec] + [blaze.module.test-util :refer [with-system]] [blaze.page-store :as page-store] [blaze.page-store-spec] [blaze.page-store.local] [blaze.page-store.spec :refer [page-store?]] - [blaze.test-util :as tu :refer [given-failed-future given-thrown with-system]] + [blaze.test-util :as tu :refer [given-thrown]] [clojure.spec.alpha :as s] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [deftest is testing]] diff --git a/modules/rest-api/.clj-kondo/config.edn b/modules/rest-api/.clj-kondo/config.edn index a686142ef..d74505790 100644 --- a/modules/rest-api/.clj-kondo/config.edn +++ b/modules/rest-api/.clj-kondo/config.edn @@ -2,7 +2,7 @@ {blaze.anomaly/when-ok clojure.core/let blaze.async.comp/do-sync clojure.core/let blaze.rest-api.metadata-handler-test/with-handler clojure.core/fn - blaze.test-util/with-system clojure.core/with-open + blaze.module.test-util/with-system clojure.core/with-open prometheus.alpha/defcounter clojure.core/def prometheus.alpha/defhistogram clojure.core/def} diff --git a/modules/rest-api/src/blaze/rest_api/capabilities.clj b/modules/rest-api/src/blaze/rest_api/capabilities.clj index 48475082a..2ebf6ca66 100644 --- a/modules/rest-api/src/blaze/rest_api/capabilities.clj +++ b/modules/rest-api/src/blaze/rest_api/capabilities.clj @@ -127,7 +127,7 @@ history-system-handler] :or {context-path ""} :as context}] - (let [release-date #fhir/dateTime"2023-07-02" + (let [release-date #fhir/dateTime"2023-08-22" capability-statement {:fhir/type :fhir/CapabilityStatement :status #fhir/code"active" diff --git a/modules/rest-api/src/blaze/rest_api/routes.clj b/modules/rest-api/src/blaze/rest_api/routes.clj index 02b0f1865..48de0298f 100644 --- a/modules/rest-api/src/blaze/rest_api/routes.clj +++ b/modules/rest-api/src/blaze/rest_api/routes.clj @@ -291,45 +291,45 @@ (cond-> (-> ["" {:middleware - (cond-> [wrap-observe-request-duration wrap-params wrap-output - wrap-error [wrap-forwarded base-url] wrap-sync] + (cond-> [wrap-observe-request-duration wrap-params wrap-output + wrap-error [wrap-forwarded base-url] wrap-sync] (seq auth-backends) (conj wrap-auth-guard)) :blaze/context-path context-path} ["" (cond-> {} (some? search-system-handler) - (assoc :get {:interaction "search-system" - :middleware [[wrap-search-db node db-sync-timeout] - wrap-link-headers] + (assoc :get {:interaction "search-system" + :middleware [[wrap-search-db node db-sync-timeout] + wrap-link-headers] :handler search-system-handler}) (some? transaction-handler) - (assoc :post {:interaction "transaction" - :middleware + (assoc :post {:interaction "transaction" + :middleware [wrap-resource [wrap-batch-handler batch-handler-promise]] :handler transaction-handler}))] ["/metadata" - {:interaction "capabilities" - :get capabilities-handler}] + {:interaction "capabilities" + :get capabilities-handler}] ["/_history" (cond-> {} (some? history-system-handler) - (assoc :get {:interaction "history-system" - :middleware [[wrap-db node db-sync-timeout] - wrap-link-headers] + (assoc :get {:interaction "history-system" + :middleware [[wrap-db node db-sync-timeout] + wrap-link-headers] :handler history-system-handler}))] ["/__page" (cond-> {:name :page} (some? search-system-handler) (assoc - :get {:interaction "search-system" - :middleware [[wrap-snapshot-db node db-sync-timeout] - wrap-link-headers] + :get {:interaction "search-system" + :middleware [[wrap-snapshot-db node db-sync-timeout] + wrap-link-headers] :handler search-system-handler} - :post {:interaction "search-system" - :middleware [[wrap-snapshot-db node db-sync-timeout] - wrap-link-headers] + :post {:interaction "search-system" + :middleware [[wrap-snapshot-db node db-sync-timeout] + wrap-link-headers] :handler search-system-handler}))]] (into (mapcat (partial operation-system-handler-route context)) diff --git a/modules/rest-api/test/blaze/rest_api/capabilities_test.clj b/modules/rest-api/test/blaze/rest_api/capabilities_test.clj index f5845f74d..221d8fa73 100644 --- a/modules/rest-api/test/blaze/rest_api/capabilities_test.clj +++ b/modules/rest-api/test/blaze/rest_api/capabilities_test.clj @@ -1,9 +1,11 @@ (ns blaze.rest-api.capabilities-test (:require [blaze.db.impl.search-param] + [blaze.fhir.test-util :refer [structure-definition-repo]] + [blaze.module.test-util :refer [with-system]] [blaze.rest-api.capabilities :as capabilities] [blaze.rest-api.capabilities-spec] - [blaze.test-util :as tu :refer [structure-definition-repo with-system]] + [blaze.test-util :as tu] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [deftest testing]] [juxt.iota :refer [given]] diff --git a/modules/rest-api/test/blaze/rest_api/metadata_handler_test.clj b/modules/rest-api/test/blaze/rest_api/metadata_handler_test.clj index fe61e655d..08fb7195a 100644 --- a/modules/rest-api/test/blaze/rest_api/metadata_handler_test.clj +++ b/modules/rest-api/test/blaze/rest_api/metadata_handler_test.clj @@ -1,8 +1,9 @@ (ns blaze.rest-api.metadata-handler-test (:require [blaze.fhir.structure-definition-repo.spec :refer [structure-definition-repo?]] + [blaze.module.test-util :refer [with-system]] [blaze.rest-api.metadata-handler] - [blaze.test-util :as tu :refer [given-thrown with-system]] + [blaze.test-util :as tu :refer [given-thrown]] [clojure.spec.alpha :as s] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [deftest testing]] diff --git a/modules/rest-api/test/blaze/rest_api/middleware/cors_test.clj b/modules/rest-api/test/blaze/rest_api/middleware/cors_test.clj index 6f238efcc..8bb4bb8fb 100644 --- a/modules/rest-api/test/blaze/rest_api/middleware/cors_test.clj +++ b/modules/rest-api/test/blaze/rest_api/middleware/cors_test.clj @@ -1,8 +1,8 @@ (ns blaze.rest-api.middleware.cors-test (:require + [blaze.fhir.test-util.ring :refer [call]] [blaze.rest-api.middleware.cors :refer [wrap-cors]] [blaze.test-util :as tu] - [blaze.test-util.ring :refer [call]] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [deftest]] [juxt.iota :refer [given]])) diff --git a/modules/rest-api/test/blaze/rest_api/middleware/forwarded_test.clj b/modules/rest-api/test/blaze/rest_api/middleware/forwarded_test.clj index e23174da8..aae1083ab 100644 --- a/modules/rest-api/test/blaze/rest_api/middleware/forwarded_test.clj +++ b/modules/rest-api/test/blaze/rest_api/middleware/forwarded_test.clj @@ -1,8 +1,8 @@ (ns blaze.rest-api.middleware.forwarded-test (:require + [blaze.fhir.test-util.ring :refer [call]] [blaze.rest-api.middleware.forwarded :refer [wrap-forwarded]] [blaze.test-util :as tu] - [blaze.test-util.ring :refer [call]] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [deftest testing]] [juxt.iota :refer [given]] diff --git a/modules/rest-api/test/blaze/rest_api/middleware/log_test.clj b/modules/rest-api/test/blaze/rest_api/middleware/log_test.clj index 88338fccd..ac6ece17c 100644 --- a/modules/rest-api/test/blaze/rest_api/middleware/log_test.clj +++ b/modules/rest-api/test/blaze/rest_api/middleware/log_test.clj @@ -1,8 +1,8 @@ (ns blaze.rest-api.middleware.log-test (:require + [blaze.fhir.test-util.ring :refer [call]] [blaze.rest-api.middleware.log :refer [wrap-log]] [blaze.test-util :as tu] - [blaze.test-util.ring :refer [call]] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [deftest is testing]] [taoensso.timbre :as log])) diff --git a/modules/rest-api/test/blaze/rest_api/middleware/output_test.clj b/modules/rest-api/test/blaze/rest_api/middleware/output_test.clj index d3834e44a..d83b8f5b4 100644 --- a/modules/rest-api/test/blaze/rest_api/middleware/output_test.clj +++ b/modules/rest-api/test/blaze/rest_api/middleware/output_test.clj @@ -2,9 +2,9 @@ (:require [blaze.fhir.spec :as fhir-spec] [blaze.fhir.spec-spec] + [blaze.fhir.test-util.ring :refer [call]] [blaze.rest-api.middleware.output :refer [wrap-output]] [blaze.test-util :as tu] - [blaze.test-util.ring :refer [call]] [clojure.data.xml :as xml] [clojure.java.io :as io] [clojure.spec.test.alpha :as st] diff --git a/modules/rest-api/test/blaze/rest_api_test.clj b/modules/rest-api/test/blaze/rest_api_test.clj index 9ffccc749..5e6687f26 100644 --- a/modules/rest-api/test/blaze/rest_api_test.clj +++ b/modules/rest-api/test/blaze/rest_api_test.clj @@ -5,12 +5,14 @@ [blaze.db.impl.search-param] [blaze.fhir.spec :as fhir-spec] [blaze.fhir.structure-definition-repo.protocols :as sdrp] + [blaze.fhir.test-util :refer [structure-definition-repo]] + [blaze.fhir.test-util.ring :refer [call]] [blaze.handler.util :as handler-util] [blaze.metrics.spec] + [blaze.module.test-util :refer [with-system]] [blaze.rest-api :as rest-api] [blaze.rest-api.middleware.metrics :as metrics] - [blaze.test-util :as tu :refer [given-thrown structure-definition-repo with-system]] - [blaze.test-util.ring :refer [call]] + [blaze.test-util :as tu :refer [given-thrown]] [clojure.spec.alpha :as s] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [are deftest is testing]] diff --git a/modules/rest-util/.clj-kondo/config.edn b/modules/rest-util/.clj-kondo/config.edn index 08719722c..3e43d873d 100644 --- a/modules/rest-util/.clj-kondo/config.edn +++ b/modules/rest-util/.clj-kondo/config.edn @@ -1,7 +1,7 @@ {:lint-as {blaze.async.comp/do-sync clojure.core/let blaze.db.api-stub/with-system-data clojure.core/with-open - blaze.test-util/with-system clojure.core/with-open} + blaze.module.test-util/with-system clojure.core/with-open} :linters {:unsorted-required-namespaces @@ -21,6 +21,7 @@ :consistent-alias {:aliases - {blaze.db.api d}}} + {blaze.db.api d + cognitect.anomalies anom}}} :skip-comments true} diff --git a/modules/rest-util/deps.edn b/modules/rest-util/deps.edn index 515ad9e9d..cfad6570b 100644 --- a/modules/rest-util/deps.edn +++ b/modules/rest-util/deps.edn @@ -12,7 +12,7 @@ {:mvn/version "5.2.2"} metosin/reitit-ring - {:mvn/version "0.6.0"} + {:mvn/version "0.7.0-alpha5"} ring/ring-core {:mvn/version "1.10.0" diff --git a/modules/rest-util/test/blaze/handler/util_test.clj b/modules/rest-util/test/blaze/handler/util_test.clj index e393810f7..a3277dcd5 100644 --- a/modules/rest-util/test/blaze/handler/util_test.clj +++ b/modules/rest-util/test/blaze/handler/util_test.clj @@ -1,8 +1,9 @@ (ns blaze.handler.util-test (:require [blaze.async.comp-spec] + [blaze.fhir.test-util :refer [given-failed-future]] [blaze.handler.util :as handler-util] - [blaze.test-util :as tu :refer [given-failed-future]] + [blaze.test-util :as tu] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [are deftest testing]] [cognitect.anomalies :as anom] diff --git a/modules/rest-util/test/blaze/middleware/fhir/db_test.clj b/modules/rest-util/test/blaze/middleware/fhir/db_test.clj index f87e38e32..90b86c820 100644 --- a/modules/rest-util/test/blaze/middleware/fhir/db_test.clj +++ b/modules/rest-util/test/blaze/middleware/fhir/db_test.clj @@ -7,9 +7,9 @@ [blaze.async.comp :as ac] [blaze.db.api :as d] [blaze.db.api-spec] + [blaze.fhir.test-util :refer [given-failed-future]] [blaze.middleware.fhir.db :as db] [blaze.middleware.fhir.db-spec] - [blaze.test-util :refer [given-failed-future]] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [deftest is testing]] [cognitect.anomalies :as anom]) diff --git a/modules/rest-util/test/blaze/middleware/fhir/error_test.clj b/modules/rest-util/test/blaze/middleware/fhir/error_test.clj index 0113beb67..c3bc14706 100644 --- a/modules/rest-util/test/blaze/middleware/fhir/error_test.clj +++ b/modules/rest-util/test/blaze/middleware/fhir/error_test.clj @@ -1,9 +1,9 @@ (ns blaze.middleware.fhir.error-test (:refer-clojure :exclude [error-handler]) (:require + [blaze.fhir.test-util.ring :refer [call]] [blaze.middleware.fhir.error :refer [wrap-error]] [blaze.test-util :as tu] - [blaze.test-util.ring :refer [call]] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [deftest is testing]] [juxt.iota :refer [given]])) diff --git a/modules/rocksdb/.clj-kondo/config.edn b/modules/rocksdb/.clj-kondo/config.edn index 480c85032..599a81c77 100644 --- a/modules/rocksdb/.clj-kondo/config.edn +++ b/modules/rocksdb/.clj-kondo/config.edn @@ -1,6 +1,7 @@ {:lint-as - {blaze.db.kv.rocksdb-test/with-system-data clojure.core/with-open - blaze.test-util/with-system clojure.core/with-open} + {blaze.anomaly/when-ok clojure.core/let + blaze.db.kv.rocksdb-test/with-system-data clojure.core/with-open + blaze.module.test-util/with-system clojure.core/with-open} :linters {:unsorted-required-namespaces @@ -20,6 +21,7 @@ :consistent-alias {:aliases - {blaze.db.kv.rocksdb.protocols p}}} + {blaze.db.kv.rocksdb.protocols p + cognitect.anomalies anom}}} :skip-comments true} diff --git a/modules/rocksdb/deps.edn b/modules/rocksdb/deps.edn index 556fab86f..efd288b48 100644 --- a/modules/rocksdb/deps.edn +++ b/modules/rocksdb/deps.edn @@ -1,5 +1,11 @@ {:deps - {blaze/kv + {blaze/byte-string + {:local/root "../byte-string"} + + blaze/coll + {:local/root "../coll"} + + blaze/kv {:local/root "../kv"} blaze/metrics @@ -16,8 +22,8 @@ {:extra-paths ["test"] :extra-deps - {blaze/test-util - {:local/root "../test-util"}}} + {blaze/module-test-util + {:local/root "../module-test-util"}}} :kaocha {:extra-deps diff --git a/modules/rocksdb/src/blaze/db/kv/rocksdb.clj b/modules/rocksdb/src/blaze/db/kv/rocksdb.clj index ae40bab2f..1e08f8218 100644 --- a/modules/rocksdb/src/blaze/db/kv/rocksdb.clj +++ b/modules/rocksdb/src/blaze/db/kv/rocksdb.clj @@ -1,5 +1,6 @@ (ns blaze.db.kv.rocksdb (:require + [blaze.anomaly :as ba :refer [when-ok]] [blaze.db.kv :as kv] [blaze.db.kv.rocksdb.impl :as impl] [blaze.db.kv.rocksdb.metrics :as metrics] @@ -184,7 +185,7 @@ (impl/datafy-tables (.getPropertiesOfAllTables db))) (-table-properties [_ column-family] - (let [cfh (impl/get-cfh cfhs column-family)] + (when-ok [cfh (ba/try-anomaly (impl/get-cfh cfhs column-family))] (impl/datafy-tables (.getPropertiesOfAllTables db cfh)))) AutoCloseable diff --git a/modules/rocksdb/src/blaze/db/kv/rocksdb/spec.clj b/modules/rocksdb/src/blaze/db/kv/rocksdb/spec.clj index ad9174aa2..ee84dc32c 100644 --- a/modules/rocksdb/src/blaze/db/kv/rocksdb/spec.clj +++ b/modules/rocksdb/src/blaze/db/kv/rocksdb/spec.clj @@ -4,6 +4,7 @@ [blaze.db.kv.rocksdb :as-alias rocksdb] [blaze.db.kv.rocksdb.db-options :as-alias db-options] [blaze.db.kv.rocksdb.protocols :as p] + [blaze.db.kv.rocksdb.table :as-alias table] [blaze.db.kv.rocksdb.write-options :as-alias write-options] [blaze.db.kv.spec] [clojure.spec.alpha :as s]) @@ -63,3 +64,15 @@ (s/def ::rocksdb/opts (s/merge ::rocksdb/db-options ::rocksdb/write-options)) + + +(s/def ::table/data-size + int?) + + +(s/def ::table/index-size + int?) + + +(s/def ::rocksdb/table + (s/keys :req-un [::table/data-size ::table/index-size])) diff --git a/modules/rocksdb/src/blaze/db/kv/rocksdb_spec.clj b/modules/rocksdb/src/blaze/db/kv/rocksdb_spec.clj index 84c295418..22f3dd540 100644 --- a/modules/rocksdb/src/blaze/db/kv/rocksdb_spec.clj +++ b/modules/rocksdb/src/blaze/db/kv/rocksdb_spec.clj @@ -3,7 +3,8 @@ [blaze.db.kv :as-alias kv] [blaze.db.kv.rocksdb :as rocksdb] [blaze.db.kv.rocksdb.spec] - [clojure.spec.alpha :as s])) + [clojure.spec.alpha :as s] + [cognitect.anomalies :as anom])) (s/fdef rocksdb/column-families @@ -27,4 +28,4 @@ (s/fdef rocksdb/table-properties :args (s/cat :store ::kv/rocksdb :column-family (s/? simple-keyword?)) - :ret int?) + :ret (s/or :properties ::rocksdb/table :anomaly ::anom/anomaly)) diff --git a/modules/rocksdb/test/blaze/db/kv/rocksdb/metrics_test.clj b/modules/rocksdb/test/blaze/db/kv/rocksdb/metrics_test.clj index cc2a69bf6..f1c6e323d 100644 --- a/modules/rocksdb/test/blaze/db/kv/rocksdb/metrics_test.clj +++ b/modules/rocksdb/test/blaze/db/kv/rocksdb/metrics_test.clj @@ -6,7 +6,8 @@ [blaze.db.kv.rocksdb.metrics-spec] [blaze.metrics.core :as metrics-core] [blaze.metrics.core-spec] - [blaze.test-util :as tu :refer [with-system]] + [blaze.module.test-util :refer [with-system]] + [blaze.test-util :as tu] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [deftest is testing]] [integrant.core :as ig] diff --git a/modules/rocksdb/test/blaze/db/kv/rocksdb_test.clj b/modules/rocksdb/test/blaze/db/kv/rocksdb_test.clj index 7f3d08258..9a14e593d 100644 --- a/modules/rocksdb/test/blaze/db/kv/rocksdb_test.clj +++ b/modules/rocksdb/test/blaze/db/kv/rocksdb_test.clj @@ -9,7 +9,8 @@ [blaze.db.kv.rocksdb-spec] [blaze.db.kv.rocksdb.impl-spec] [blaze.db.kv.rocksdb.metrics :as-alias metrics] - [blaze.test-util :as tu :refer [bytes= given-thrown with-system]] + [blaze.module.test-util :refer [with-system]] + [blaze.test-util :as tu :refer [bytes= given-thrown]] [clojure.spec.alpha :as s] [clojure.spec.test.alpha :as st] [clojure.string :as str] @@ -734,26 +735,27 @@ (deftest table-properties-test - (with-system [{db ::kv/rocksdb} (config (new-temp-dir!))] - (run! - (fn [i] - (kv/put! - db - (bs/to-byte-array (bs/from-hex (str/upper-case (Long/toHexString i)))) - (apply ba (range 10000)))) - (range 10000 20000)) - - (given (rocksdb/table-properties db) - count := 1 - [0 :comparator-name] := "leveldb.BytewiseComparator" - [0 :compression-name] := "LZ4" - [0 :data-size] := 2168082 - [0 :index-size] := 86351 - [0 :num-data-blocks] := 6631 - [0 :num-entries] := 6631 - [0 :top-level-index-size] := 0 - [0 :total-raw-key-size] := 66310 - [0 :total-raw-value-size] := 66310000)) + (testing "default column-family" + (with-system [{db ::kv/rocksdb} (config (new-temp-dir!))] + (run! + (fn [i] + (kv/put! + db + (bs/to-byte-array (bs/from-hex (str/upper-case (Long/toHexString i)))) + (apply ba (range 10000)))) + (range 10000 20000)) + + (given (rocksdb/table-properties db) + count := 1 + [0 :comparator-name] := "leveldb.BytewiseComparator" + [0 :compression-name] := "LZ4" + [0 :data-size] := 2168082 + [0 :index-size] := 86351 + [0 :num-data-blocks] := 6631 + [0 :num-entries] := 6631 + [0 :top-level-index-size] := 0 + [0 :total-raw-key-size] := 66310 + [0 :total-raw-value-size] := 66310000))) (testing "with column-family" (with-system [{db ::kv/rocksdb} (a-config (new-temp-dir!))] @@ -776,7 +778,13 @@ [0 :num-entries] := 6631 [0 :top-level-index-size] := 0 [0 :total-raw-key-size] := 66310 - [0 :total-raw-value-size] := 66310000)))) + [0 :total-raw-value-size] := 66310000))) + + (testing "with unknown column-family" + (with-system [{db ::kv/rocksdb} (config (new-temp-dir!))] + (given (rocksdb/table-properties db :column-family-143119) + ::anom/category := ::anom/not-found + ::anom/message := "column family `column-family-143119` not found")))) (deftest compact-range-test diff --git a/modules/scheduler/.clj-kondo/config.edn b/modules/scheduler/.clj-kondo/config.edn index d12a895c1..e2271fd78 100644 --- a/modules/scheduler/.clj-kondo/config.edn +++ b/modules/scheduler/.clj-kondo/config.edn @@ -1,5 +1,5 @@ {:lint-as - {blaze.test-util/with-system clojure.core/with-open} + {blaze.module.test-util/with-system clojure.core/with-open} :linters {:unsorted-required-namespaces @@ -15,6 +15,10 @@ {:level :warning} :warn-on-reflection - {:level :warning :warn-only-on-interop true}} + {:level :warning :warn-only-on-interop true} + + :consistent-alias + {:aliases + {blaze.scheduler sched}}} :skip-comments true} diff --git a/modules/scheduler/Makefile b/modules/scheduler/Makefile index 8eb60f27a..196a53ceb 100644 --- a/modules/scheduler/Makefile +++ b/modules/scheduler/Makefile @@ -1,16 +1,13 @@ lint: clj-kondo --lint src test deps.edn -prep: - clojure -X:deps prep - -test: prep +test: clojure -M:test:kaocha --profile :ci -test-coverage: prep +test-coverage: clojure -M:test:coverage clean: rm -rf .clj-kondo/.cache .cpcache target -.PHONY: lint prep test test-coverage clean +.PHONY: lint test test-coverage clean diff --git a/modules/scheduler/README.md b/modules/scheduler/README.md new file mode 100644 index 000000000..9d65e4158 --- /dev/null +++ b/modules/scheduler/README.md @@ -0,0 +1,3 @@ +# Scheduler + +A scheduler that can run functions at fixed intervals. diff --git a/modules/scheduler/deps.edn b/modules/scheduler/deps.edn index fed381b85..60aa0109c 100644 --- a/modules/scheduler/deps.edn +++ b/modules/scheduler/deps.edn @@ -1,5 +1,8 @@ {:deps - {blaze/module-base + {blaze/executor + {:local/root "../executor"} + + blaze/module-base {:local/root "../module-base"}} :aliases @@ -7,8 +10,8 @@ {:extra-paths ["test"] :extra-deps - {blaze/test-util - {:local/root "../test-util"}}} + {blaze/module-test-util + {:local/root "../module-test-util"}}} :kaocha {:extra-deps diff --git a/modules/scheduler/test/blaze/scheduler_test.clj b/modules/scheduler/test/blaze/scheduler_test.clj index dafbb15af..16181c7c1 100644 --- a/modules/scheduler/test/blaze/scheduler_test.clj +++ b/modules/scheduler/test/blaze/scheduler_test.clj @@ -1,9 +1,10 @@ (ns blaze.scheduler-test (:require [blaze.executors :as ex] + [blaze.module.test-util :refer [with-system]] [blaze.scheduler :as sched] [blaze.scheduler-spec] - [blaze.test-util :as tu :refer [with-system]] + [blaze.test-util :as tu] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [deftest is testing]] [integrant.core :as ig] diff --git a/modules/server/.clj-kondo/config.edn b/modules/server/.clj-kondo/config.edn index 7566ee080..d09c1673b 100644 --- a/modules/server/.clj-kondo/config.edn +++ b/modules/server/.clj-kondo/config.edn @@ -1,6 +1,6 @@ {:lint-as {blaze.async.comp/do-sync clojure.core/let - blaze.test-util/with-system clojure.core/with-open} + blaze.module.test-util/with-system clojure.core/with-open} :linters {:unsorted-required-namespaces diff --git a/modules/server/Makefile b/modules/server/Makefile index 7510b665c..182928813 100644 --- a/modules/server/Makefile +++ b/modules/server/Makefile @@ -1,13 +1,10 @@ lint: clj-kondo --lint src test deps.edn -prep: - clojure -X:deps prep - -test: prep +test: clojure -M:test:kaocha --profile :ci -test-coverage: prep +test-coverage: clojure -M:test:coverage deps-tree: @@ -19,4 +16,4 @@ deps-list: clean: rm -rf .clj-kondo/.cache .cpcache target -.PHONY: lint prep test test-coverage deps-tree deps-list clean +.PHONY: lint test test-coverage deps-tree deps-list clean diff --git a/modules/server/deps.edn b/modules/server/deps.edn index c9ef13d30..5fb7bf649 100644 --- a/modules/server/deps.edn +++ b/modules/server/deps.edn @@ -6,7 +6,7 @@ {:local/root "../module-base"} info.sunng/ring-jetty9-adapter - {:mvn/version "0.22.0" + {:mvn/version "0.22.1" :exclusions [commons-fileupload/commons-fileupload crypto-equality/crypto-equality @@ -17,8 +17,8 @@ {:extra-paths ["test"] :extra-deps - {blaze/test-util - {:local/root "../test-util"} + {blaze/module-test-util + {:local/root "../module-test-util"} hato/hato {:mvn/version "0.9.0"}}} diff --git a/modules/server/test/blaze/server_test.clj b/modules/server/test/blaze/server_test.clj index 139273a28..fc2557f27 100644 --- a/modules/server/test/blaze/server_test.clj +++ b/modules/server/test/blaze/server_test.clj @@ -2,8 +2,9 @@ (:refer-clojure :exclude [error-handler]) (:require [blaze.anomaly :as ba] + [blaze.module.test-util :refer [with-system]] [blaze.server] - [blaze.test-util :as tu :refer [given-thrown with-system]] + [blaze.test-util :as tu :refer [given-thrown]] [clojure.spec.alpha :as s] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [deftest testing]] diff --git a/modules/spec/deps.edn b/modules/spec/deps.edn index e7265026f..30aaa8254 100644 --- a/modules/spec/deps.edn +++ b/modules/spec/deps.edn @@ -1,3 +1,3 @@ {:deps {clojure.java-time/clojure.java-time - {:mvn/version "1.2.0"}}} + {:mvn/version "1.3.0"}}} diff --git a/modules/test-util/.clj-kondo/config.edn b/modules/test-util/.clj-kondo/config.edn index 52a3a2d2f..34fefe2e9 100644 --- a/modules/test-util/.clj-kondo/config.edn +++ b/modules/test-util/.clj-kondo/config.edn @@ -1,7 +1,4 @@ -{:lint-as - {blaze.fhir.spec.generators/def-resource-gen clojure.core/def} - - :linters +{:linters {:unsorted-required-namespaces {:level :error} @@ -12,10 +9,7 @@ {:level :error} :reduce-without-init - {:level :warning} - - :unresolved-symbol - {:exclude [(blaze.fhir.spec.generators/def-resource-gen)]}} + {:level :warning}} :warn-on-reflection {:level :warning :warn-only-on-interop true} diff --git a/modules/test-util/deps.edn b/modules/test-util/deps.edn index d640c2630..7e8d34df8 100644 --- a/modules/test-util/deps.edn +++ b/modules/test-util/deps.edn @@ -1,23 +1,5 @@ {:deps - {blaze/anomaly - {:local/root "../anomaly"} - - blaze/async - {:local/root "../async"} - - blaze/byte-buffer - {:local/root "../byte-buffer"} - - blaze/executor - {:local/root "../executor"} - - blaze/fhir-structure - {:local/root "../fhir-structure"} - - integrant/integrant - {:mvn/version "0.8.1"} - - org.clojars.akiel/iota + {org.clojars.akiel/iota {:mvn/version "0.1"} org.clojure/test.check diff --git a/modules/test-util/src/blaze/test_util.clj b/modules/test-util/src/blaze/test_util.clj index dc023d445..30b77d6d8 100644 --- a/modules/test-util/src/blaze/test_util.clj +++ b/modules/test-util/src/blaze/test_util.clj @@ -1,18 +1,11 @@ (ns blaze.test-util (:require - [blaze.anomaly :as ba] - [blaze.byte-buffer :as bb] - [blaze.executors :as ex] - [blaze.fhir.structure-definition-repo] [clojure.spec.test.alpha :as st] [clojure.test :refer [is]] [clojure.test.check :as tc] - [integrant.core :as ig] [juxt.iota :refer [given]]) (:import - [java.time Clock Instant ZoneId] - [java.util Arrays Random] - [java.util.concurrent Executors TimeUnit])) + [java.util Arrays])) (set! *warn-on-reflection* true) @@ -31,61 +24,6 @@ ~@body)) -(defmacro given-failed-future [future & body] - `(given (try (deref ~future) (is false) (catch Exception e# (ba/anomaly e#))) - ~@body)) - - -(defmacro with-system - "Runs `body` inside a system that is initialized from `config`, bound to - `binding-form` and finally halted." - [[binding-form config] & body] - `(let [system# (ig/init ~config)] - (try - (let [~binding-form system#] - ~@body) - (finally - (ig/halt! system#))))) - - -(defmethod ig/init-key :blaze.test/fixed-clock - [_ _] - (Clock/fixed Instant/EPOCH (ZoneId/of "UTC"))) - - -(defmethod ig/init-key :blaze.test/system-clock - [_ _] - (Clock/systemUTC)) - - -(defmethod ig/init-key :blaze.test/fixed-rng-fn - [_ {:keys [n] :or {n 0}}] - #(proxy [Random] [] - (nextLong [] n))) - - -(defmethod ig/init-key :blaze.test/fixed-rng - [_ _] - (let [state (atom 0)] - (proxy [Random] [] - (nextBytes [byte-array] - (assert (= 20 (count byte-array))) - (let [bb (bb/wrap byte-array)] - (bb/set-position! bb 12) - (bb/put-long! bb (swap! state inc))))))) - - -(defmethod ig/init-key :blaze.test/executor - [_ _] - (Executors/newFixedThreadPool 4)) - - -(defmethod ig/halt-key! :blaze.test/executor - [_ executor] - (ex/shutdown! executor) - (ex/await-termination executor 10 TimeUnit/SECONDS)) - - (defmacro satisfies-prop [num-tests prop] `(let [result# (tc/quick-check ~num-tests ~prop)] (if (instance? Throwable (:result result#)) @@ -102,18 +40,7 @@ (Arrays/equals a b)) -(defonce structure-definition-repo - (:blaze.fhir/structure-definition-repo - (ig/init {:blaze.fhir/structure-definition-repo {}}))) - - (defn fixture [f] (st/instrument) (f) (st/unstrument)) - - -(defn extract-txs-body [more] - (if (vector? (first more)) - [(first more) (next more)] - [[] more])) diff --git a/modules/thread-pool-executor-collector/.clj-kondo/config.edn b/modules/thread-pool-executor-collector/.clj-kondo/config.edn index d12a895c1..a25d19101 100644 --- a/modules/thread-pool-executor-collector/.clj-kondo/config.edn +++ b/modules/thread-pool-executor-collector/.clj-kondo/config.edn @@ -1,5 +1,5 @@ {:lint-as - {blaze.test-util/with-system clojure.core/with-open} + {blaze.module.test-util/with-system clojure.core/with-open} :linters {:unsorted-required-namespaces diff --git a/modules/thread-pool-executor-collector/deps.edn b/modules/thread-pool-executor-collector/deps.edn index f43aa5ec8..aec66b30d 100644 --- a/modules/thread-pool-executor-collector/deps.edn +++ b/modules/thread-pool-executor-collector/deps.edn @@ -10,8 +10,11 @@ {:extra-paths ["test"] :extra-deps - {blaze/test-util - {:local/root "../test-util"}}} + {blaze/executor + {:local/root "../executor"} + + blaze/module-test-util + {:local/root "../module-test-util"}}} :kaocha {:extra-deps diff --git a/modules/thread-pool-executor-collector/test/blaze/thread_pool_executor_collector_test.clj b/modules/thread-pool-executor-collector/test/blaze/thread_pool_executor_collector_test.clj index b72b906b3..249e652b6 100644 --- a/modules/thread-pool-executor-collector/test/blaze/thread_pool_executor_collector_test.clj +++ b/modules/thread-pool-executor-collector/test/blaze/thread_pool_executor_collector_test.clj @@ -2,7 +2,8 @@ (:require [blaze.executors :as ex] [blaze.metrics.core :as metrics] - [blaze.test-util :as tu :refer [given-thrown with-system]] + [blaze.module.test-util :refer [with-system]] + [blaze.test-util :as tu :refer [given-thrown]] [blaze.thread-pool-executor-collector] [blaze.thread-pool-executor-collector.spec :as spec] [clojure.spec.alpha :as s] diff --git a/src/blaze/system.clj b/src/blaze/system.clj index 9bb8512d1..0205c8917 100644 --- a/src/blaze/system.clj +++ b/src/blaze/system.clj @@ -84,7 +84,7 @@ (def ^:private root-config - {:blaze/version "0.22.0" + {:blaze/version "0.22.1" :blaze/clock {} diff --git a/test/blaze/handler/app_test.clj b/test/blaze/handler/app_test.clj index 8a8b53962..f8268c43e 100644 --- a/test/blaze/handler/app_test.clj +++ b/test/blaze/handler/app_test.clj @@ -1,8 +1,9 @@ (ns blaze.handler.app-test (:require + [blaze.fhir.test-util.ring :refer [call]] [blaze.handler.app] - [blaze.test-util :as tu :refer [given-thrown with-system]] - [blaze.test-util.ring :refer [call]] + [blaze.module.test-util :refer [with-system]] + [blaze.test-util :as tu :refer [given-thrown]] [clojure.spec.alpha :as s] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [deftest testing]] diff --git a/test/blaze/handler/health_test.clj b/test/blaze/handler/health_test.clj index 89deb7d66..c4678b2de 100644 --- a/test/blaze/handler/health_test.clj +++ b/test/blaze/handler/health_test.clj @@ -1,8 +1,9 @@ (ns blaze.handler.health-test (:require + [blaze.fhir.test-util.ring :refer [call]] [blaze.handler.health] - [blaze.test-util :as tu :refer [with-system]] - [blaze.test-util.ring :refer [call]] + [blaze.module.test-util :refer [with-system]] + [blaze.test-util :as tu] [clojure.spec.test.alpha :as st] [clojure.test :as test :refer [deftest]] [juxt.iota :refer [given]] diff --git a/test/blaze/system_test.clj b/test/blaze/system_test.clj index 11f4a5c02..483868ddf 100644 --- a/test/blaze/system_test.clj +++ b/test/blaze/system_test.clj @@ -3,17 +3,19 @@ [blaze.async.comp :as ac] [blaze.db.api-stub :refer [mem-node-config]] [blaze.fhir.spec :as fhir-spec] + [blaze.fhir.test-util :refer [structure-definition-repo]] + [blaze.fhir.test-util.ring :refer [call]] [blaze.interaction.delete] [blaze.interaction.read] [blaze.interaction.search-system] [blaze.interaction.search-type] [blaze.interaction.transaction] + [blaze.module.test-util :refer [with-system]] [blaze.page-store.protocols :as pp] [blaze.rest-api] [blaze.system :as system] [blaze.system-spec] - [blaze.test-util :as tu :refer [structure-definition-repo with-system]] - [blaze.test-util.ring :refer [call]] + [blaze.test-util :as tu] [buddy.auth.protocols :as ap] [clojure.spec.alpha :as s] [clojure.spec.test.alpha :as st]