Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
package ca.uhn.fhir.interceptor.model;

import com.google.common.collect.Lists;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;

import java.time.LocalDate;
import java.util.stream.Stream;

import static ca.uhn.fhir.interceptor.model.RequestPartitionId.allPartitions;
import static ca.uhn.fhir.interceptor.model.RequestPartitionId.defaultPartition;
import static ca.uhn.fhir.interceptor.model.RequestPartitionId.fromPartitionId;
import static ca.uhn.fhir.interceptor.model.RequestPartitionId.fromPartitionIds;
import static ca.uhn.fhir.interceptor.model.RequestPartitionId.fromPartitionNames;
import static ca.uhn.fhir.interceptor.model.RequestPartitionId.stringifyForKey;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

class RequestPartitionIdTest {

private static final LocalDate PARTITION_DATE = LocalDate.of(2020, 1, 1);
private static final String PARTITION_NAME_1 = "Name1";
private static final String PARTITION_NAME_2 = "Name2";
private static final Integer PARTITION_ID_1 = 1;
private static final Integer PARTITION_ID_2 = 2;
private static final Integer PARTITION_ID_123 = 123;

@Test
void testEqualsAndHashCode() {
RequestPartitionId expected = fromPartitionId(PARTITION_ID_123, PARTITION_DATE);
RequestPartitionId actual = fromPartitionId(PARTITION_ID_123, PARTITION_DATE);

assertEquals(expected, actual);
assertEquals(expected.hashCode(), actual.hashCode());
assertNotEquals(expected, "123");
assertNotEquals(expected, null);
}

@Test
void testPartitionHelpers() {
IDefaultPartitionSettings settings = new IDefaultPartitionSettings() {
@Override
public Integer getDefaultPartitionId() {
return 0;
}
};

assertTrue(fromPartitionId(null).isPartition(null));
assertTrue(fromPartitionId(null).isDefaultPartition());
assertThat(fromPartitionId(null).hasDefaultPartitionId(null)).isTrue();
assertThat(defaultPartition(settings).isPartition(0)).isTrue();
assertThat(defaultPartition(settings).isDefaultPartition()).isFalse();
assertThat(allPartitions().isAllPartitions()).isTrue();
assertThat(allPartitions().isPartition(0)).isFalse();
assertThat(fromPartitionIds(0, 2).isPartition(0)).isFalse();
}

@Test
void testMergeIds() {
assertEquals(fromPartitionIds(1, 2, 3, 4), fromPartitionIds(1, 2, 3).mergeIds(fromPartitionIds(1, 2, 4)));
assertEquals(allPartitions(), allPartitions().mergeIds(fromPartitionIds(1, 2, 4)));
assertEquals(allPartitions(), fromPartitionIds(1, 2, 3).mergeIds(allPartitions()));
assertEquals(fromPartitionIds(1, 2, 3, null), fromPartitionIds(1, 2, 3).mergeIds(fromPartitionId(null)));
}

@ParameterizedTest
@MethodSource("testStringifyForKeyTestCases")
void testStringifyForKey(RequestPartitionId theRequestPartitionId, String theExpectedString) {
assertEquals(theExpectedString, stringifyForKey(theRequestPartitionId));
}

static Stream<Object[]> testStringifyForKeyTestCases() {
return Stream.of(
new Object[] {allPartitions(), "(all)"},
new Object[] {fromPartitionId(null), "null"},
new Object[] {fromPartitionIds(1, 2, 3), "1 2 3"},
new Object[] {fromPartitionIds(null, 2, 3), "null 2 3"},
new Object[] {RequestPartitionId.allPartitionsWithPartitionIds(1, 2, 3), "(all) 1 2 3"});
}

record ContainsTestCase(String description, RequestPartitionId left, RequestPartitionId right, Comparison comparison) {
enum Comparison {
LEFT_CONTAINS_RIGHT,
RIGHT_CONTAINS_LEFT,
EQUAL,
NEITHER;

boolean expectLeftContainsRight() {
return this == LEFT_CONTAINS_RIGHT || this == EQUAL;
}

boolean expectRightContainsLeft() {
return this == RIGHT_CONTAINS_LEFT || this == EQUAL;
}

boolean expectEqual() {
return this == EQUAL;
}
}

@Override
public String toString() {
return "%s: %s %s".formatted(description, left, right);
}
}

@ParameterizedTest(name = "{0}")
@MethodSource("getContainsTestCases")
void testContains(ContainsTestCase theTestCase) {
RequestPartitionId left = theTestCase.left();
RequestPartitionId right = theTestCase.right();
ContainsTestCase.Comparison comparison = theTestCase.comparison();

assertThat(left.contains(right)).describedAs("%s: left contains right", theTestCase.description).isEqualTo(comparison.expectLeftContainsRight());
assertThat(right.contains(left)).describedAs("%s: right contains left", theTestCase.description).isEqualTo(comparison.expectRightContainsLeft());
assertThat(right.equals(left)).describedAs("%s: are equal", theTestCase.description).isEqualTo(comparison.expectEqual());
}

static ContainsTestCase[] getContainsTestCases() {
IDefaultPartitionSettings nullDefaultPartition = new IDefaultPartitionSettings() {};
return new ContainsTestCase[] {
new ContainsTestCase("all vs all", allPartitions(), allPartitions(), ContainsTestCase.Comparison.EQUAL),
new ContainsTestCase("all vs normal", allPartitions(), fromPartitionIds(1, 2, 3), ContainsTestCase.Comparison.LEFT_CONTAINS_RIGHT),
new ContainsTestCase("equal partition id lists", fromPartitionIds(1, 2, 3), fromPartitionIds(1, 2, 3), ContainsTestCase.Comparison.EQUAL),
new ContainsTestCase("different id lists incomparable", fromPartitionIds(1, 2, 5), fromPartitionIds(1, 2, 9), ContainsTestCase.Comparison.NEITHER),
new ContainsTestCase("default as null contains", fromPartitionIds(1, 2, null), defaultPartition(nullDefaultPartition), ContainsTestCase.Comparison.LEFT_CONTAINS_RIGHT),
new ContainsTestCase("names equivalent", fromPartitionNames("A", "B"), fromPartitionNames("A", "B"), ContainsTestCase.Comparison.EQUAL),
new ContainsTestCase("names left contains right", fromPartitionNames("A", "B"), fromPartitionNames("A"), ContainsTestCase.Comparison.LEFT_CONTAINS_RIGHT),
new ContainsTestCase("names left ids right", fromPartitionNames("A", "B"), fromPartitionIds(1, 2), ContainsTestCase.Comparison.NEITHER)
};
}

@Test
void testJsonRoundTripPreservesSemanticFields() throws Exception {
RequestPartitionId start = RequestPartitionId.forPartitionIdsAndNames(Lists.newArrayList(PARTITION_NAME_1, PARTITION_NAME_2), Lists.newArrayList(PARTITION_ID_1, PARTITION_ID_2), PARTITION_DATE);

RequestPartitionId end = assertSerDeserSer(start);

assertThat(end.getPartitionDate()).isEqualTo(PARTITION_DATE);
assertThat(end.getPartitionNames()).containsExactly(PARTITION_NAME_1, PARTITION_NAME_2);
assertThat(end.getPartitionIds()).containsExactly(PARTITION_ID_1, PARTITION_ID_2);
assertThat(end.getPartitionIdsWithoutDefault()).containsExactly(PARTITION_ID_1, PARTITION_ID_2);
assertThat(end.getFirstPartitionIdOrNull()).isEqualTo(PARTITION_ID_1);
assertThat(end.getFirstPartitionNameOrNull()).isEqualTo(PARTITION_NAME_1);
}

@Test
void testJsonRoundTripPreservesAllAndDefaultPartitions() throws Exception {
RequestPartitionId all = assertSerDeserSer(allPartitions());
assertThat(all.isAllPartitions()).isTrue();
assertThat(all.hasPartitionIds()).isFalse();

RequestPartitionId defaultPartition = assertSerDeserSer(fromPartitionId(null));
assertThat(defaultPartition.getPartitionIds()).containsExactly((Integer) null);
assertThat(defaultPartition.isDefaultPartition()).isTrue();
}

private RequestPartitionId assertSerDeserSer(RequestPartitionId start) throws Exception {
String json = start.asJson();
RequestPartitionId end = RequestPartitionId.fromJson(json);
assertEquals(start, end);
assertEquals(start.asJson(), end.asJson());
return end;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
package ca.uhn.fhir.parser.json.jackson;

import ca.uhn.fhir.parser.DataFormatException;
import ca.uhn.fhir.parser.json.BaseJsonLikeArray;
import ca.uhn.fhir.parser.json.BaseJsonLikeObject;
import ca.uhn.fhir.parser.json.BaseJsonLikeValue;
import ca.uhn.fhir.parser.json.JsonLikeStructure;
import org.junit.jupiter.api.Test;

import java.io.StringReader;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

class JacksonStructureTest {

private static final String STRING_FIELD = "string-value";
private static final String NUMBER_FIELD = "number-value";
private static final String BOOLEAN_FIELD = "boolean-value";
private static final String OBJECT_FIELD = "object-value";
private static final String ARRAY_FIELD = "array-value";
private static final String STRING_VALUE = "text";
private static final String NUMBER_VALUE = "123";
private static final String BOOLEAN_VALUE = "true";
private static final String NULL_FIELD = "null-value";
private static final String NESTED_FIELD = "nested";
private static final String NESTED_VALUE = "value";
private static final int ARRAY_VALUE_ONE = 1;
private static final int ARRAY_VALUE_TWO = 2;

@Test
void getInstanceReturnsNewJacksonStructure() {
JacksonStructure structure = new JacksonStructure();

JsonLikeStructure instance = structure.getInstance();

assertThat(instance).isInstanceOf(JacksonStructure.class);
assertThat(instance).isNotSameAs(structure);
}

@Test
void loadsObjectRootAndExposesExpectedValueTypes() {
JacksonStructure structure = new JacksonStructure();

structure.load(new StringReader("""
{
"%s": "%s",
"%s": %s,
"%s": %s,
"%s": null,
"%s": {"%s": "%s"},
"%s": [%d, {"%s": %d}]
}
""".formatted(STRING_FIELD, STRING_VALUE, NUMBER_FIELD, NUMBER_VALUE, BOOLEAN_FIELD, BOOLEAN_VALUE, NULL_FIELD, OBJECT_FIELD, NESTED_FIELD, NESTED_VALUE, ARRAY_FIELD, ARRAY_VALUE_ONE, NESTED_FIELD, ARRAY_VALUE_TWO)));

BaseJsonLikeObject root = structure.getRootObject();
assertThat(root).isNotNull();

assertThat(root.get(STRING_FIELD))
.extracting(BaseJsonLikeValue::getJsonType, BaseJsonLikeValue::getDataType, BaseJsonLikeValue::getAsString)
.containsExactly(BaseJsonLikeValue.ValueType.SCALAR, BaseJsonLikeValue.ScalarType.STRING, STRING_VALUE);

assertThat(root.get(NUMBER_FIELD))
.extracting(BaseJsonLikeValue::getJsonType, BaseJsonLikeValue::getDataType, BaseJsonLikeValue::getAsString)
.containsExactly(BaseJsonLikeValue.ValueType.SCALAR, BaseJsonLikeValue.ScalarType.NUMBER, NUMBER_VALUE);

assertThat(root.get(BOOLEAN_FIELD))
.extracting(BaseJsonLikeValue::getJsonType, BaseJsonLikeValue::getDataType, BaseJsonLikeValue::getAsBoolean)
.containsExactly(BaseJsonLikeValue.ValueType.SCALAR, BaseJsonLikeValue.ScalarType.BOOLEAN, true);

assertThat(root.get(NULL_FIELD).isNull()).isTrue();

BaseJsonLikeObject nestedObject = root.get(OBJECT_FIELD).getAsObject();
assertThat(nestedObject).isNotNull();
assertThat(nestedObject.get(NESTED_FIELD).getAsString()).isEqualTo(NESTED_VALUE);

BaseJsonLikeArray array = root.get(ARRAY_FIELD).getAsArray();
assertThat(array).isNotNull();
assertThat(array.size()).isEqualTo(2);
assertThat(array.get(0).getAsNumber()).isEqualTo(ARRAY_VALUE_ONE);
assertThat(array.get(1).getAsObject().get("nested").getAsNumber()).isEqualTo(ARRAY_VALUE_TWO);
}

@Test
void loadsArrayRootWhenAllowedAndRejectsItFromGetRootObject() {
JacksonStructure structure = new JacksonStructure();

structure.load(new StringReader("[\"a\", 2, false]"), true);

assertThatThrownBy(structure::getRootObject)
.isInstanceOf(DataFormatException.class)
.hasMessageContaining("must start with '{'");
}

@Test
void rejectsArrayRootWhenNotAllowed() {
JacksonStructure structure = new JacksonStructure();

assertThatThrownBy(() -> structure.load(new StringReader("[1, 2, 3]")))
.isInstanceOf(DataFormatException.class)
.hasMessageContaining("must be '{'");
}

@Test
void rejectsMalformedJsonContent() {
JacksonStructure structure = new JacksonStructure();

assertThatThrownBy(() -> structure.load(new StringReader("{\"resourceType\":\"Patient\"} trailing")))
.isInstanceOf(DataFormatException.class)
.hasMessageContaining("Failed to parse JSON encoded FHIR content");
}
}
Loading
Loading