mirror of
https://github.com/hapifhir/hapi-fhir.git
synced 2025-03-26 01:48:28 +00:00
Add ChainedDelegateConsentService with pluggable vote strategy
Introduce some plumbing utils to combine consent votes.
This commit is contained in:
parent
6a365f8722
commit
239bf8d441
hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/7_6_0
hapi-fhir-server/src
main/java/ca/uhn/fhir/rest/server/interceptor/consent
ConsentOperationStatusEnum.javaConsentOutcome.javaConstantConsentService.javaIConsentVote.javaMultiDelegateConsentService.java
test/java/ca/uhn/fhir/rest/server/interceptor/consent
4
hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/7_6_0/6366-consent-plumbing.yaml
Normal file
4
hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/7_6_0/6366-consent-plumbing.yaml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
---
|
||||||
|
type: add
|
||||||
|
issue: 6366
|
||||||
|
title: "Add plumbing for combining IConsentServices with different vote tally strategies"
|
@ -21,7 +21,7 @@ package ca.uhn.fhir.rest.server.interceptor.consent;
|
|||||||
|
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
public enum ConsentOperationStatusEnum {
|
public enum ConsentOperationStatusEnum implements IConsentVote {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The requested operation cannot proceed, and an operation outcome suitable for
|
* The requested operation cannot proceed, and an operation outcome suitable for
|
||||||
@ -59,53 +59,52 @@ public enum ConsentOperationStatusEnum {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Does this vote abstain from the verdict?
|
||||||
|
* I.e. this == PROCEED
|
||||||
|
* @return true if this vote can be ignored
|
||||||
|
*/
|
||||||
|
boolean isAbstain() {
|
||||||
|
return this == PROCEED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Does this vote participate from the verdict?
|
||||||
|
* I.e. this != PROCEED
|
||||||
|
* @return false if this vote can be ignored
|
||||||
|
*/
|
||||||
|
boolean isActiveVote() {
|
||||||
|
return this != PROCEED;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ConsentOperationStatusEnum getStatus() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Evaluate verdicts in order, taking the first "decision" (i.e. first non-PROCEED) verdict.
|
* Evaluate verdicts in order, taking the first "decision" (i.e. first non-PROCEED) verdict.
|
||||||
*
|
*
|
||||||
* @return the first decisive verdict, or PROCEED when empty or all PROCEED.
|
* @return the first decisive verdict, or PROCEED when empty or all PROCEED.
|
||||||
*/
|
*/
|
||||||
|
public static ConsentOperationStatusEnum serialReduce(Stream<ConsentOperationStatusEnum> theVoteStream) {
|
||||||
|
return IConsentVote.serialReduce(PROCEED, theVoteStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ConsentOperationStatusEnum parallelReduce(Stream<ConsentOperationStatusEnum> theVoteStream) {
|
||||||
|
return IConsentVote.parallelReduce(PROCEED, theVoteStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @deprecated for rename */
|
||||||
|
@Deprecated(forRemoval = true)
|
||||||
public static ConsentOperationStatusEnum serialEvaluate(Stream<ConsentOperationStatusEnum> theVoteStream) {
|
public static ConsentOperationStatusEnum serialEvaluate(Stream<ConsentOperationStatusEnum> theVoteStream) {
|
||||||
return theVoteStream.filter(verdict -> PROCEED != verdict).findFirst().orElse(PROCEED);
|
return serialReduce(theVoteStream);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** @deprecated for rename */
|
||||||
* Evaluate verdicts in order, taking the first "decision" (i.e. first non-PROCEED) verdict.
|
@Deprecated(forRemoval = true)
|
||||||
*
|
|
||||||
* @param theNextVerdict the next verdict to consider
|
|
||||||
* @return the combined verdict
|
|
||||||
*/
|
|
||||||
public ConsentOperationStatusEnum serialReduce(ConsentOperationStatusEnum theNextVerdict) {
|
|
||||||
if (this != PROCEED) {
|
|
||||||
return this;
|
|
||||||
} else {
|
|
||||||
return theNextVerdict;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Evaluate all verdicts together, allowing any to veto (i.e. REJECT) the operation.
|
|
||||||
* <ul>
|
|
||||||
* <li>If any vote is REJECT, then the result is REJECT.
|
|
||||||
* <li>If no vote is REJECT, and any vote is AUTHORIZED, then the result is AUTHORIZED.
|
|
||||||
* <li>If no vote is REJECT or AUTHORIZED, the result is PROCEED.
|
|
||||||
* </ul>
|
|
||||||
*
|
|
||||||
* @return REJECT if any reject, AUTHORIZED if no REJECT and some AUTHORIZED, PROCEED if empty or all PROCEED
|
|
||||||
*/
|
|
||||||
public static ConsentOperationStatusEnum parallelEvaluate(Stream<ConsentOperationStatusEnum> theVoteStream) {
|
public static ConsentOperationStatusEnum parallelEvaluate(Stream<ConsentOperationStatusEnum> theVoteStream) {
|
||||||
return theVoteStream.reduce(PROCEED, ConsentOperationStatusEnum::parallelReduce);
|
return parallelReduce(theVoteStream);
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Evaluate two verdicts together, allowing either to veto (i.e. REJECT) the operation.
|
|
||||||
*
|
|
||||||
* @return REJECT if either reject, AUTHORIZED if no REJECT and some AUTHORIZED, PROCEED otherwise
|
|
||||||
*/
|
|
||||||
public ConsentOperationStatusEnum parallelReduce(ConsentOperationStatusEnum theNextVerdict) {
|
|
||||||
if (theNextVerdict.getPrecedence() > this.getPrecedence()) {
|
|
||||||
return theNextVerdict;
|
|
||||||
} else {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,9 @@ import org.apache.commons.lang3.Validate;
|
|||||||
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
|
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
|
|
||||||
public class ConsentOutcome {
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
public class ConsentOutcome implements IConsentVote {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convenience constant containing <code>new ConsentOutcome(ConsentOperationStatusEnum.PROCEED)</code>
|
* Convenience constant containing <code>new ConsentOutcome(ConsentOperationStatusEnum.PROCEED)</code>
|
||||||
@ -67,6 +69,29 @@ public class ConsentOutcome {
|
|||||||
myResource = theResource;
|
myResource = theResource;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Evaluate all verdicts together, allowing any to veto (i.e. REJECT) the operation.
|
||||||
|
* <ul>
|
||||||
|
* <li>If any vote is REJECT, then the result is a REJECT vote.
|
||||||
|
* <li>If no vote is REJECT, and any vote is AUTHORIZED, then the result is one of the AUTHORIZED votes.
|
||||||
|
* <li>If no vote is REJECT or AUTHORIZED, the result is a PROCEED vote.
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @return REJECT if any reject, AUTHORIZED if no REJECT and some AUTHORIZED, PROCEED if empty or all PROCEED
|
||||||
|
*/
|
||||||
|
public static ConsentOutcome parallelReduce(Stream<ConsentOutcome> theOutcomes) {
|
||||||
|
return IConsentVote.parallelReduce(ConsentOutcome.PROCEED, theOutcomes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Evaluate verdicts in order, taking the first "decision" (i.e. first non-PROCEED) verdict.
|
||||||
|
*
|
||||||
|
* @return the first decisive verdict, or theSeed when empty or all PROCEED.
|
||||||
|
*/
|
||||||
|
public static ConsentOutcome serialReduce(Stream<ConsentOutcome> theStream) {
|
||||||
|
return IConsentVote.serialReduce(ConsentOutcome.PROCEED, theStream);
|
||||||
|
}
|
||||||
|
|
||||||
public ConsentOperationStatusEnum getStatus() {
|
public ConsentOperationStatusEnum getStatus() {
|
||||||
return myStatus;
|
return myStatus;
|
||||||
}
|
}
|
||||||
|
48
hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/consent/ConstantConsentService.java
Normal file
48
hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/consent/ConstantConsentService.java
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
package ca.uhn.fhir.rest.server.interceptor.consent;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||||
|
import jakarta.annotation.Nonnull;
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Consent Service that returns a fixed verdict.
|
||||||
|
*/
|
||||||
|
public class ConstantConsentService implements IConsentService {
|
||||||
|
@Nonnull
|
||||||
|
final ConsentOutcome myResult;
|
||||||
|
|
||||||
|
public static ConstantConsentService constantService(ConsentOperationStatusEnum theResult) {
|
||||||
|
return new ConstantConsentService(new ConsentOutcome(theResult));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConstantConsentService(@Nonnull ConsentOutcome theResult) {
|
||||||
|
myResult = theResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
private @Nonnull ConsentOutcome getOutcome() {
|
||||||
|
return myResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ConsentOutcome startOperation(RequestDetails theRequestDetails, IConsentContextServices theContextServices) {
|
||||||
|
return getOutcome();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean shouldProcessCanSeeResource(
|
||||||
|
RequestDetails theRequestDetails, IConsentContextServices theContextServices) {
|
||||||
|
return myResult.getStatus().isActiveVote();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ConsentOutcome canSeeResource(
|
||||||
|
RequestDetails theRequestDetails, IBaseResource theResource, IConsentContextServices theContextServices) {
|
||||||
|
return getOutcome();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ConsentOutcome willSeeResource(
|
||||||
|
RequestDetails theRequestDetails, IBaseResource theResource, IConsentContextServices theContextServices) {
|
||||||
|
return getOutcome();
|
||||||
|
}
|
||||||
|
}
|
71
hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/consent/IConsentVote.java
Normal file
71
hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/consent/IConsentVote.java
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
package ca.uhn.fhir.rest.server.interceptor.consent;
|
||||||
|
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Something that produces a vote, along with static
|
||||||
|
* tools for combining votes.
|
||||||
|
*/
|
||||||
|
public interface IConsentVote {
|
||||||
|
/**
|
||||||
|
* Get the vote
|
||||||
|
* @return the vote
|
||||||
|
*/
|
||||||
|
ConsentOperationStatusEnum getStatus();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Evaluate all verdicts together, allowing any to veto (i.e. REJECT) the operation.
|
||||||
|
* <ul>
|
||||||
|
* <li>If any vote is REJECT, then the result is REJECT.
|
||||||
|
* <li>If no vote is REJECT, and any vote is AUTHORIZED, then the result is AUTHORIZED.
|
||||||
|
* <li>If no vote is REJECT or AUTHORIZED, the result is PROCEED.
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @return REJECT if any reject, AUTHORIZED if no REJECT and some AUTHORIZED, PROCEED if empty or all PROCEED
|
||||||
|
*/
|
||||||
|
static <T extends IConsentVote> T parallelReduce(T theSeed, Stream<T> theVoteStream) {
|
||||||
|
return theVoteStream.reduce(theSeed, IConsentVote::parallelReduce);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Evaluate two votes together, allowing either to veto (i.e. REJECT) the operation.
|
||||||
|
*
|
||||||
|
* @return REJECT if either reject, AUTHORIZED if no REJECT and some AUTHORIZED, PROCEED otherwise
|
||||||
|
*/
|
||||||
|
static <T extends IConsentVote> T parallelReduce(T theAccumulator, T theNextVoter) {
|
||||||
|
if (theNextVoter.getStatus().getPrecedence()
|
||||||
|
< theAccumulator.getStatus().getPrecedence()) {
|
||||||
|
return theAccumulator;
|
||||||
|
} else {
|
||||||
|
return theNextVoter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Evaluate verdicts in order, taking the first "decision" (i.e. first non-PROCEED) verdict.
|
||||||
|
*
|
||||||
|
* @return the first decisive verdict, or theSeed when empty or all PROCEED.
|
||||||
|
*/
|
||||||
|
static <T extends IConsentVote> T serialReduce(T theSeed, Stream<T> theVoterStream) {
|
||||||
|
return theVoterStream.filter(IConsentVote::isActiveVote).findFirst().orElse(theSeed);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Evaluate verdicts in order, taking the first "decision" (i.e. first non-PROCEED) verdict.
|
||||||
|
*
|
||||||
|
* @param theAccumulator the verdict so fat
|
||||||
|
* @param theNextVoter the next verdict to consider
|
||||||
|
* @return the combined verdict
|
||||||
|
*/
|
||||||
|
static <T extends IConsentVote> T serialReduce(T theAccumulator, T theNextVoter) {
|
||||||
|
if (theAccumulator.getStatus().isAbstain()) {
|
||||||
|
return theNextVoter;
|
||||||
|
} else {
|
||||||
|
return theAccumulator;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static <T extends IConsentVote> boolean isActiveVote(T nextVoter) {
|
||||||
|
return nextVoter.getStatus().isActiveVote();
|
||||||
|
}
|
||||||
|
}
|
74
hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/consent/MultiDelegateConsentService.java
Normal file
74
hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/consent/MultiDelegateConsentService.java
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
package ca.uhn.fhir.rest.server.interceptor.consent;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||||
|
import jakarta.annotation.Nonnull;
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IConsentService combiner over several delegates with pluggable combination strategy
|
||||||
|
*/
|
||||||
|
public class MultiDelegateConsentService implements IConsentService {
|
||||||
|
private final Collection<IConsentService> myDelegates;
|
||||||
|
private final Function<Stream<ConsentOutcome>, ConsentOutcome> myVoteCombiner;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Combine several consent services allowing any to veto.
|
||||||
|
*/
|
||||||
|
public static @Nonnull MultiDelegateConsentService withParallelVoting(
|
||||||
|
@Nonnull List<IConsentService> theDelegateConsentServices) {
|
||||||
|
return new MultiDelegateConsentService(ConsentOutcome::parallelReduce, theDelegateConsentServices);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Combine several consent services with first non-PROCEED vote win.
|
||||||
|
*/
|
||||||
|
public static @Nonnull MultiDelegateConsentService withSerialVoting(
|
||||||
|
@Nonnull List<IConsentService> theDelegateConsentServices) {
|
||||||
|
return new MultiDelegateConsentService(ConsentOutcome::serialReduce, theDelegateConsentServices);
|
||||||
|
}
|
||||||
|
|
||||||
|
private MultiDelegateConsentService(
|
||||||
|
Function<Stream<ConsentOutcome>, ConsentOutcome> theVoteCombiner,
|
||||||
|
Collection<IConsentService> theDelegates) {
|
||||||
|
myVoteCombiner = theVoteCombiner;
|
||||||
|
myDelegates = theDelegates;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ConsentOutcome startOperation(RequestDetails theRequestDetails, IConsentContextServices theContextServices) {
|
||||||
|
return myVoteCombiner.apply(myDelegates.stream()
|
||||||
|
.map(nextDelegate -> nextDelegate.startOperation(theRequestDetails, theContextServices)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return true if any of the delegates return true.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean shouldProcessCanSeeResource(
|
||||||
|
RequestDetails theRequestDetails, IConsentContextServices theContextServices) {
|
||||||
|
return myDelegates.stream()
|
||||||
|
.map(nextDelegate -> nextDelegate.shouldProcessCanSeeResource(theRequestDetails, theContextServices))
|
||||||
|
.filter(nextShould -> nextShould)
|
||||||
|
.findFirst()
|
||||||
|
.orElse(Boolean.FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ConsentOutcome canSeeResource(
|
||||||
|
RequestDetails theRequestDetails, IBaseResource theResource, IConsentContextServices theContextServices) {
|
||||||
|
return myVoteCombiner.apply(myDelegates.stream()
|
||||||
|
.map(nextDelegate -> nextDelegate.canSeeResource(theRequestDetails, theResource, theContextServices)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ConsentOutcome willSeeResource(
|
||||||
|
RequestDetails theRequestDetails, IBaseResource theResource, IConsentContextServices theContextServices) {
|
||||||
|
return myVoteCombiner.apply(myDelegates.stream()
|
||||||
|
.map(nextDelegate -> nextDelegate.willSeeResource(theRequestDetails, theResource, theContextServices)));
|
||||||
|
}
|
||||||
|
}
|
@ -1,130 +1,14 @@
|
|||||||
package ca.uhn.fhir.rest.server.interceptor.consent;
|
package ca.uhn.fhir.rest.server.interceptor.consent;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.params.ParameterizedTest;
|
|
||||||
import org.junit.jupiter.params.provider.CsvSource;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
import static ca.uhn.fhir.rest.server.interceptor.consent.ConsentOperationStatusEnum.AUTHORIZED;
|
import static ca.uhn.fhir.rest.server.interceptor.consent.ConsentOperationStatusEnum.AUTHORIZED;
|
||||||
import static ca.uhn.fhir.rest.server.interceptor.consent.ConsentOperationStatusEnum.PROCEED;
|
import static ca.uhn.fhir.rest.server.interceptor.consent.ConsentOperationStatusEnum.PROCEED;
|
||||||
import static ca.uhn.fhir.rest.server.interceptor.consent.ConsentOperationStatusEnum.REJECT;
|
import static ca.uhn.fhir.rest.server.interceptor.consent.ConsentOperationStatusEnum.REJECT;
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
class ConsentOperationStatusEnumTest {
|
class ConsentOperationStatusEnumTest {
|
||||||
|
|
||||||
/**
|
|
||||||
* With "serial" evaluation, the first non-PROCEED verdict wins.
|
|
||||||
*/
|
|
||||||
@ParameterizedTest
|
|
||||||
@CsvSource(textBlock = """
|
|
||||||
REJECT REJECT REJECT , REJECT
|
|
||||||
REJECT REJECT PROCEED , REJECT
|
|
||||||
REJECT REJECT AUTHORIZED, REJECT
|
|
||||||
REJECT PROCEED REJECT , REJECT
|
|
||||||
REJECT PROCEED PROCEED , REJECT
|
|
||||||
REJECT PROCEED AUTHORIZED, REJECT
|
|
||||||
REJECT AUTHORIZED REJECT , REJECT
|
|
||||||
REJECT AUTHORIZED PROCEED , REJECT
|
|
||||||
REJECT AUTHORIZED AUTHORIZED, REJECT
|
|
||||||
PROCEED REJECT REJECT , REJECT
|
|
||||||
PROCEED REJECT PROCEED , REJECT
|
|
||||||
PROCEED REJECT AUTHORIZED, REJECT
|
|
||||||
PROCEED PROCEED REJECT , REJECT
|
|
||||||
PROCEED PROCEED PROCEED , PROCEED
|
|
||||||
PROCEED PROCEED AUTHORIZED, AUTHORIZED
|
|
||||||
PROCEED AUTHORIZED REJECT , AUTHORIZED
|
|
||||||
PROCEED AUTHORIZED PROCEED , AUTHORIZED
|
|
||||||
PROCEED AUTHORIZED AUTHORIZED, AUTHORIZED
|
|
||||||
AUTHORIZED REJECT REJECT , AUTHORIZED
|
|
||||||
AUTHORIZED REJECT PROCEED , AUTHORIZED
|
|
||||||
AUTHORIZED REJECT AUTHORIZED, AUTHORIZED
|
|
||||||
AUTHORIZED PROCEED REJECT , AUTHORIZED
|
|
||||||
AUTHORIZED PROCEED PROCEED , AUTHORIZED
|
|
||||||
AUTHORIZED PROCEED AUTHORIZED, AUTHORIZED
|
|
||||||
AUTHORIZED AUTHORIZED REJECT , AUTHORIZED
|
|
||||||
AUTHORIZED AUTHORIZED PROCEED , AUTHORIZED
|
|
||||||
AUTHORIZED AUTHORIZED AUTHORIZED, AUTHORIZED
|
|
||||||
""")
|
|
||||||
void testSerialEvaluation_choosesFirstVerdict(String theInput, ConsentOperationStatusEnum theExpectedResult) {
|
|
||||||
// given
|
|
||||||
Stream<ConsentOperationStatusEnum> consentOperationStatusEnumStream = Arrays.stream(theInput.split(" +"))
|
|
||||||
.map(String::trim)
|
|
||||||
.map(ConsentOperationStatusEnum::valueOf);
|
|
||||||
|
|
||||||
// when
|
|
||||||
ConsentOperationStatusEnum result = ConsentOperationStatusEnum.serialEvaluate(consentOperationStatusEnumStream);
|
|
||||||
|
|
||||||
assertEquals(theExpectedResult, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
@ParameterizedTest
|
|
||||||
@CsvSource(textBlock = """
|
|
||||||
REJECT , REJECT , REJECT
|
|
||||||
REJECT , PROCEED , REJECT
|
|
||||||
REJECT , AUTHORIZED, REJECT
|
|
||||||
AUTHORIZED, REJECT , AUTHORIZED
|
|
||||||
AUTHORIZED, PROCEED , AUTHORIZED
|
|
||||||
AUTHORIZED, AUTHORIZED, AUTHORIZED
|
|
||||||
PROCEED , REJECT , REJECT
|
|
||||||
PROCEED , PROCEED , PROCEED
|
|
||||||
PROCEED , AUTHORIZED, AUTHORIZED
|
|
||||||
""")
|
|
||||||
void testSerialReduction_choosesFirstVerdict(ConsentOperationStatusEnum theFirst, ConsentOperationStatusEnum theSecond, ConsentOperationStatusEnum theExpectedResult) {
|
|
||||||
|
|
||||||
// when
|
|
||||||
ConsentOperationStatusEnum result = theFirst.serialReduce(theSecond);
|
|
||||||
|
|
||||||
assertEquals(theExpectedResult, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* With "parallel" evaluation, the "strongest" verdict wins.
|
|
||||||
* REJECT > AUTHORIZED > PROCEED.
|
|
||||||
*/
|
|
||||||
@ParameterizedTest
|
|
||||||
@CsvSource(textBlock = """
|
|
||||||
REJECT REJECT REJECT , REJECT
|
|
||||||
REJECT REJECT PROCEED , REJECT
|
|
||||||
REJECT REJECT AUTHORIZED, REJECT
|
|
||||||
REJECT PROCEED REJECT , REJECT
|
|
||||||
REJECT PROCEED PROCEED , REJECT
|
|
||||||
REJECT PROCEED AUTHORIZED, REJECT
|
|
||||||
REJECT AUTHORIZED REJECT , REJECT
|
|
||||||
REJECT AUTHORIZED PROCEED , REJECT
|
|
||||||
REJECT AUTHORIZED AUTHORIZED, REJECT
|
|
||||||
PROCEED REJECT REJECT , REJECT
|
|
||||||
PROCEED REJECT PROCEED , REJECT
|
|
||||||
PROCEED REJECT AUTHORIZED, REJECT
|
|
||||||
PROCEED PROCEED REJECT , REJECT
|
|
||||||
PROCEED PROCEED PROCEED , PROCEED
|
|
||||||
PROCEED PROCEED AUTHORIZED, AUTHORIZED
|
|
||||||
PROCEED AUTHORIZED REJECT , REJECT
|
|
||||||
PROCEED AUTHORIZED PROCEED , AUTHORIZED
|
|
||||||
PROCEED AUTHORIZED AUTHORIZED, AUTHORIZED
|
|
||||||
AUTHORIZED REJECT REJECT , REJECT
|
|
||||||
AUTHORIZED REJECT PROCEED , REJECT
|
|
||||||
AUTHORIZED REJECT AUTHORIZED, REJECT
|
|
||||||
AUTHORIZED PROCEED REJECT , REJECT
|
|
||||||
AUTHORIZED PROCEED PROCEED , AUTHORIZED
|
|
||||||
AUTHORIZED PROCEED AUTHORIZED, AUTHORIZED
|
|
||||||
AUTHORIZED AUTHORIZED REJECT , REJECT
|
|
||||||
AUTHORIZED AUTHORIZED PROCEED , AUTHORIZED
|
|
||||||
AUTHORIZED AUTHORIZED AUTHORIZED, AUTHORIZED
|
|
||||||
""")
|
|
||||||
void testParallelReduction_strongestVerdictWins(String theInput, ConsentOperationStatusEnum theExpectedResult) {
|
|
||||||
// given
|
|
||||||
Stream<ConsentOperationStatusEnum> consentOperationStatusEnumStream = Arrays.stream(theInput.split(" +"))
|
|
||||||
.map(String::trim)
|
|
||||||
.map(ConsentOperationStatusEnum::valueOf);
|
|
||||||
|
|
||||||
// when
|
|
||||||
ConsentOperationStatusEnum result = ConsentOperationStatusEnum.parallelEvaluate(consentOperationStatusEnumStream);
|
|
||||||
|
|
||||||
assertEquals(theExpectedResult, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testStrengthOrder() {
|
void testStrengthOrder() {
|
||||||
|
70
hapi-fhir-server/src/test/java/ca/uhn/fhir/rest/server/interceptor/consent/ConstantConsentServiceTest.java
Normal file
70
hapi-fhir-server/src/test/java/ca/uhn/fhir/rest/server/interceptor/consent/ConstantConsentServiceTest.java
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
package ca.uhn.fhir.rest.server.interceptor.consent;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.rest.api.server.SystemRequestDetails;
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.EnumSource;
|
||||||
|
|
||||||
|
import static ca.uhn.fhir.rest.server.interceptor.consent.IConsentContextServices.NULL_IMPL;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
class ConstantConsentServiceTest {
|
||||||
|
SystemRequestDetails mySrd = new SystemRequestDetails();
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@EnumSource(ConsentOperationStatusEnum.class)
|
||||||
|
void testStartOperation(ConsentOperationStatusEnum theStatus) {
|
||||||
|
// given
|
||||||
|
var svc = ConstantConsentService.constantService(theStatus);
|
||||||
|
|
||||||
|
// when
|
||||||
|
var outcome = svc.startOperation(mySrd,NULL_IMPL);
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertEquals(outcome.getStatus(), theStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* There's no point calling canSee if we return PROCEED.
|
||||||
|
*/
|
||||||
|
@ParameterizedTest
|
||||||
|
@EnumSource(ConsentOperationStatusEnum.class)
|
||||||
|
void testShouldProcessCanSeeResource(ConsentOperationStatusEnum theStatus) {
|
||||||
|
// given
|
||||||
|
var svc = ConstantConsentService.constantService(theStatus);
|
||||||
|
|
||||||
|
// when
|
||||||
|
boolean outcome = svc.shouldProcessCanSeeResource(mySrd,NULL_IMPL);
|
||||||
|
|
||||||
|
// then there's no point calling canSee if we return PROCEED.
|
||||||
|
boolean isNotAbstain = theStatus != ConsentOperationStatusEnum.PROCEED;
|
||||||
|
assertEquals(outcome, isNotAbstain);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@EnumSource(ConsentOperationStatusEnum.class)
|
||||||
|
void testCanSeeResource(ConsentOperationStatusEnum theStatus) {
|
||||||
|
// given
|
||||||
|
var svc = ConstantConsentService.constantService(theStatus);
|
||||||
|
|
||||||
|
// when
|
||||||
|
var outcome = svc.canSeeResource(mySrd, null, NULL_IMPL);
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertEquals(outcome.getStatus(), theStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@EnumSource(ConsentOperationStatusEnum.class)
|
||||||
|
void testWillSeeResource(ConsentOperationStatusEnum theStatus) {
|
||||||
|
// given
|
||||||
|
var svc = ConstantConsentService.constantService(theStatus);
|
||||||
|
|
||||||
|
// when
|
||||||
|
var outcome = svc.willSeeResource(mySrd, null, NULL_IMPL);
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertEquals(outcome.getStatus(), theStatus);
|
||||||
|
}
|
||||||
|
}
|
156
hapi-fhir-server/src/test/java/ca/uhn/fhir/rest/server/interceptor/consent/IConsentVoteTest.java
Normal file
156
hapi-fhir-server/src/test/java/ca/uhn/fhir/rest/server/interceptor/consent/IConsentVoteTest.java
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
package ca.uhn.fhir.rest.server.interceptor.consent;
|
||||||
|
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.CsvSource;
|
||||||
|
|
||||||
|
import jakarta.annotation.Nonnull;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
class IConsentVoteTest {
|
||||||
|
|
||||||
|
/** col1: stream of votes, col2: expected verdict */
|
||||||
|
public static final String SERIAL_STREAM_EXPECTATION = """
|
||||||
|
REJECT REJECT REJECT , REJECT
|
||||||
|
REJECT REJECT PROCEED , REJECT
|
||||||
|
REJECT REJECT AUTHORIZED, REJECT
|
||||||
|
REJECT PROCEED REJECT , REJECT
|
||||||
|
REJECT PROCEED PROCEED , REJECT
|
||||||
|
REJECT PROCEED AUTHORIZED, REJECT
|
||||||
|
REJECT AUTHORIZED REJECT , REJECT
|
||||||
|
REJECT AUTHORIZED PROCEED , REJECT
|
||||||
|
REJECT AUTHORIZED AUTHORIZED, REJECT
|
||||||
|
PROCEED REJECT REJECT , REJECT
|
||||||
|
PROCEED REJECT PROCEED , REJECT
|
||||||
|
PROCEED REJECT AUTHORIZED, REJECT
|
||||||
|
PROCEED PROCEED REJECT , REJECT
|
||||||
|
PROCEED PROCEED PROCEED , PROCEED
|
||||||
|
PROCEED PROCEED AUTHORIZED, AUTHORIZED
|
||||||
|
PROCEED AUTHORIZED REJECT , AUTHORIZED
|
||||||
|
PROCEED AUTHORIZED PROCEED , AUTHORIZED
|
||||||
|
PROCEED AUTHORIZED AUTHORIZED, AUTHORIZED
|
||||||
|
AUTHORIZED REJECT REJECT , AUTHORIZED
|
||||||
|
AUTHORIZED REJECT PROCEED , AUTHORIZED
|
||||||
|
AUTHORIZED REJECT AUTHORIZED, AUTHORIZED
|
||||||
|
AUTHORIZED PROCEED REJECT , AUTHORIZED
|
||||||
|
AUTHORIZED PROCEED PROCEED , AUTHORIZED
|
||||||
|
AUTHORIZED PROCEED AUTHORIZED, AUTHORIZED
|
||||||
|
AUTHORIZED AUTHORIZED REJECT , AUTHORIZED
|
||||||
|
AUTHORIZED AUTHORIZED PROCEED , AUTHORIZED
|
||||||
|
AUTHORIZED AUTHORIZED AUTHORIZED, AUTHORIZED
|
||||||
|
""";
|
||||||
|
|
||||||
|
/** col1: stream of votes, col2: expected verdict */
|
||||||
|
public static final String PARALLEL_STREAM_EXPECTATION = """
|
||||||
|
REJECT REJECT REJECT , REJECT
|
||||||
|
REJECT REJECT PROCEED , REJECT
|
||||||
|
REJECT REJECT AUTHORIZED, REJECT
|
||||||
|
REJECT PROCEED REJECT , REJECT
|
||||||
|
REJECT PROCEED PROCEED , REJECT
|
||||||
|
REJECT PROCEED AUTHORIZED, REJECT
|
||||||
|
REJECT AUTHORIZED REJECT , REJECT
|
||||||
|
REJECT AUTHORIZED PROCEED , REJECT
|
||||||
|
REJECT AUTHORIZED AUTHORIZED, REJECT
|
||||||
|
PROCEED REJECT REJECT , REJECT
|
||||||
|
PROCEED REJECT PROCEED , REJECT
|
||||||
|
PROCEED REJECT AUTHORIZED, REJECT
|
||||||
|
PROCEED PROCEED REJECT , REJECT
|
||||||
|
PROCEED PROCEED PROCEED , PROCEED
|
||||||
|
PROCEED PROCEED AUTHORIZED, AUTHORIZED
|
||||||
|
PROCEED AUTHORIZED REJECT , REJECT
|
||||||
|
PROCEED AUTHORIZED PROCEED , AUTHORIZED
|
||||||
|
PROCEED AUTHORIZED AUTHORIZED, AUTHORIZED
|
||||||
|
AUTHORIZED REJECT REJECT , REJECT
|
||||||
|
AUTHORIZED REJECT PROCEED , REJECT
|
||||||
|
AUTHORIZED REJECT AUTHORIZED, REJECT
|
||||||
|
AUTHORIZED PROCEED REJECT , REJECT
|
||||||
|
AUTHORIZED PROCEED PROCEED , AUTHORIZED
|
||||||
|
AUTHORIZED PROCEED AUTHORIZED, AUTHORIZED
|
||||||
|
AUTHORIZED AUTHORIZED REJECT , REJECT
|
||||||
|
AUTHORIZED AUTHORIZED PROCEED , AUTHORIZED
|
||||||
|
AUTHORIZED AUTHORIZED AUTHORIZED, AUTHORIZED
|
||||||
|
""";
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@CsvSource(textBlock = """
|
||||||
|
REJECT , REJECT , REJECT
|
||||||
|
REJECT , PROCEED , REJECT
|
||||||
|
REJECT , AUTHORIZED, REJECT
|
||||||
|
AUTHORIZED, REJECT , AUTHORIZED
|
||||||
|
AUTHORIZED, PROCEED , AUTHORIZED
|
||||||
|
AUTHORIZED, AUTHORIZED, AUTHORIZED
|
||||||
|
PROCEED , REJECT , REJECT
|
||||||
|
PROCEED , PROCEED , PROCEED
|
||||||
|
PROCEED , AUTHORIZED, AUTHORIZED
|
||||||
|
""")
|
||||||
|
void testSerialReduction_choosesFirstVerdict(ConsentOperationStatusEnum theFirst, ConsentOperationStatusEnum theSecond, ConsentOperationStatusEnum theExpectedResult) {
|
||||||
|
|
||||||
|
// when
|
||||||
|
ConsentOperationStatusEnum result = IConsentVote.serialReduce(theFirst, theSecond);
|
||||||
|
|
||||||
|
assertEquals(theExpectedResult, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* With "serial" evaluation, the first non-PROCEED verdict wins.
|
||||||
|
*/
|
||||||
|
@ParameterizedTest
|
||||||
|
@CsvSource(textBlock = SERIAL_STREAM_EXPECTATION)
|
||||||
|
void testSerialStreamReduction_choosesFirstVerdict(String theInput, ConsentOperationStatusEnum theExpectedResult) {
|
||||||
|
// given
|
||||||
|
Stream<ConsentOperationStatusEnum> consentOperationStatusEnumStream = splitEnumsToStream(theInput);
|
||||||
|
|
||||||
|
// when
|
||||||
|
ConsentOperationStatusEnum result = ConsentOperationStatusEnum.serialReduce(consentOperationStatusEnumStream);
|
||||||
|
|
||||||
|
assertEquals(theExpectedResult, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
static @Nonnull Stream<ConsentOperationStatusEnum> splitEnumsToStream(String theInput) {
|
||||||
|
return Arrays.stream(theInput.split(" +"))
|
||||||
|
.map(String::trim)
|
||||||
|
.map(ConsentOperationStatusEnum::valueOf);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@CsvSource(textBlock = """
|
||||||
|
REJECT , REJECT , REJECT
|
||||||
|
REJECT , PROCEED , REJECT
|
||||||
|
REJECT , AUTHORIZED, REJECT
|
||||||
|
AUTHORIZED, REJECT , REJECT
|
||||||
|
AUTHORIZED, PROCEED , AUTHORIZED
|
||||||
|
AUTHORIZED, AUTHORIZED, AUTHORIZED
|
||||||
|
PROCEED , REJECT , REJECT
|
||||||
|
PROCEED , PROCEED , PROCEED
|
||||||
|
PROCEED , AUTHORIZED, AUTHORIZED
|
||||||
|
""")
|
||||||
|
void testParallelReduction_choosesStrongestVerdict(ConsentOperationStatusEnum theFirst, ConsentOperationStatusEnum theSecond, ConsentOperationStatusEnum theExpectedResult) {
|
||||||
|
|
||||||
|
// when
|
||||||
|
ConsentOperationStatusEnum result = IConsentVote.parallelReduce(theFirst, theSecond);
|
||||||
|
|
||||||
|
assertEquals(theExpectedResult, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* With "parallel" evaluation, the "strongest" verdict wins.
|
||||||
|
* REJECT > AUTHORIZED > PROCEED.
|
||||||
|
*/
|
||||||
|
@ParameterizedTest
|
||||||
|
@CsvSource(textBlock = PARALLEL_STREAM_EXPECTATION)
|
||||||
|
void testParallelStreamReduction_strongestVerdictWins(String theInput, ConsentOperationStatusEnum theExpectedResult) {
|
||||||
|
// given
|
||||||
|
Stream<ConsentOperationStatusEnum> consentOperationStatusEnumStream = splitEnumsToStream(theInput);
|
||||||
|
|
||||||
|
// when
|
||||||
|
ConsentOperationStatusEnum result = ConsentOperationStatusEnum.parallelReduce(consentOperationStatusEnumStream);
|
||||||
|
|
||||||
|
assertEquals(theExpectedResult, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
166
hapi-fhir-server/src/test/java/ca/uhn/fhir/rest/server/interceptor/consent/MultiDelegateConsentServiceTest.java
Normal file
166
hapi-fhir-server/src/test/java/ca/uhn/fhir/rest/server/interceptor/consent/MultiDelegateConsentServiceTest.java
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
package ca.uhn.fhir.rest.server.interceptor.consent;
|
||||||
|
|
||||||
|
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||||
|
import ca.uhn.fhir.rest.api.server.SystemRequestDetails;
|
||||||
|
import org.junit.jupiter.api.Nested;
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.CsvSource;
|
||||||
|
|
||||||
|
import jakarta.annotation.Nonnull;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static ca.uhn.fhir.rest.server.interceptor.consent.MultiDelegateConsentService.withParallelVoting;
|
||||||
|
import static ca.uhn.fhir.rest.server.interceptor.consent.MultiDelegateConsentService.withSerialVoting;
|
||||||
|
import static ca.uhn.fhir.rest.server.interceptor.consent.IConsentVoteTest.PARALLEL_STREAM_EXPECTATION;
|
||||||
|
import static ca.uhn.fhir.rest.server.interceptor.consent.IConsentVoteTest.SERIAL_STREAM_EXPECTATION;
|
||||||
|
import static ca.uhn.fhir.rest.server.interceptor.consent.IConsentVoteTest.splitEnumsToStream;
|
||||||
|
import static org.apache.commons.lang3.StringUtils.defaultString;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
class MultiDelegateConsentServiceTest {
|
||||||
|
SystemRequestDetails mySrd = new SystemRequestDetails();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* "parallel" means any voter can veto.
|
||||||
|
*/
|
||||||
|
@Nested
|
||||||
|
class ParallelEvaluation {
|
||||||
|
MultiDelegateConsentService myService;
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@CsvSource(textBlock = PARALLEL_STREAM_EXPECTATION)
|
||||||
|
void testStartOperation(String theInput, ConsentOperationStatusEnum theExpectedResult) {
|
||||||
|
|
||||||
|
var services = splitEnumsToStream(theInput).map(result -> (IConsentService)ConstantConsentService.constantService(result)).toList();
|
||||||
|
myService = withParallelVoting(services);
|
||||||
|
|
||||||
|
var verdict = myService.startOperation(mySrd, IConsentContextServices.NULL_IMPL);
|
||||||
|
|
||||||
|
assertEquals(theExpectedResult.getStatus(), verdict.getStatus());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@CsvSource(textBlock = """
|
||||||
|
, false
|
||||||
|
true , true
|
||||||
|
false , false
|
||||||
|
false true , true
|
||||||
|
true false , true
|
||||||
|
""")
|
||||||
|
void testCanSeeResource(String theInput, boolean theExpectedResult) {
|
||||||
|
|
||||||
|
List<IConsentService> consentServices = Arrays.stream(defaultString(theInput).split(" +"))
|
||||||
|
.map(String::trim)
|
||||||
|
.map(Boolean::valueOf)
|
||||||
|
.map(MultiDelegateConsentServiceTest::buildConsentShouldProcessCanSee)
|
||||||
|
.toList();
|
||||||
|
myService = withParallelVoting(consentServices);
|
||||||
|
|
||||||
|
var result = myService.shouldProcessCanSeeResource(mySrd, IConsentContextServices.NULL_IMPL);
|
||||||
|
|
||||||
|
assertEquals(theExpectedResult, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@CsvSource(textBlock = PARALLEL_STREAM_EXPECTATION)
|
||||||
|
void testCanSeeResource(String theInput, ConsentOperationStatusEnum theExpectedResult) {
|
||||||
|
|
||||||
|
var services = splitEnumsToStream(theInput).map(result -> (IConsentService)ConstantConsentService.constantService(result)).toList();
|
||||||
|
myService = withParallelVoting(services);
|
||||||
|
|
||||||
|
var verdict = myService.canSeeResource(mySrd, null, IConsentContextServices.NULL_IMPL);
|
||||||
|
|
||||||
|
assertEquals(theExpectedResult.getStatus(), verdict.getStatus());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@CsvSource(textBlock = PARALLEL_STREAM_EXPECTATION)
|
||||||
|
void testWillSeeResource(String theInput, ConsentOperationStatusEnum theExpectedResult) {
|
||||||
|
|
||||||
|
var services = splitEnumsToStream(theInput).map(result -> (IConsentService)ConstantConsentService.constantService(result)).toList();
|
||||||
|
myService = withParallelVoting(services);
|
||||||
|
|
||||||
|
var verdict = myService.willSeeResource(mySrd, null, IConsentContextServices.NULL_IMPL);
|
||||||
|
|
||||||
|
assertEquals(theExpectedResult.getStatus(), verdict.getStatus());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* "serial" means first comited vote wins
|
||||||
|
*/
|
||||||
|
@Nested
|
||||||
|
class SerialEvaluation {
|
||||||
|
MultiDelegateConsentService myService;
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@CsvSource(textBlock = SERIAL_STREAM_EXPECTATION)
|
||||||
|
void testStartOperation(String theInput, ConsentOperationStatusEnum theExpectedResult) {
|
||||||
|
|
||||||
|
var services = splitEnumsToStream(theInput).map(result -> (IConsentService)ConstantConsentService.constantService(result)).toList();
|
||||||
|
myService = withSerialVoting(services);
|
||||||
|
|
||||||
|
var verdict = myService.startOperation(mySrd, IConsentContextServices.NULL_IMPL);
|
||||||
|
|
||||||
|
assertEquals(theExpectedResult.getStatus(), verdict.getStatus());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@CsvSource(textBlock = """
|
||||||
|
, false
|
||||||
|
true , true
|
||||||
|
false , false
|
||||||
|
false true , true
|
||||||
|
true false , true
|
||||||
|
""")
|
||||||
|
void testCanSeeResource(String theInput, boolean theExpectedResult) {
|
||||||
|
|
||||||
|
List<IConsentService> consentServices = Arrays.stream(defaultString(theInput).split(" +"))
|
||||||
|
.map(String::trim)
|
||||||
|
.map(Boolean::valueOf)
|
||||||
|
.map(MultiDelegateConsentServiceTest::buildConsentShouldProcessCanSee)
|
||||||
|
.toList();
|
||||||
|
myService = withSerialVoting(consentServices);
|
||||||
|
|
||||||
|
var result = myService.shouldProcessCanSeeResource(mySrd, IConsentContextServices.NULL_IMPL);
|
||||||
|
|
||||||
|
assertEquals(theExpectedResult, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@CsvSource(textBlock = SERIAL_STREAM_EXPECTATION)
|
||||||
|
void testCanSeeResource(String theInput, ConsentOperationStatusEnum theExpectedResult) {
|
||||||
|
|
||||||
|
var services = splitEnumsToStream(theInput).map(result -> (IConsentService)ConstantConsentService.constantService(result)).toList();
|
||||||
|
myService = withSerialVoting(services);
|
||||||
|
|
||||||
|
var verdict = myService.canSeeResource(mySrd, null, IConsentContextServices.NULL_IMPL);
|
||||||
|
|
||||||
|
assertEquals(theExpectedResult.getStatus(), verdict.getStatus());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@CsvSource(textBlock = SERIAL_STREAM_EXPECTATION)
|
||||||
|
void testWillSeeResource(String theInput, ConsentOperationStatusEnum theExpectedResult) {
|
||||||
|
|
||||||
|
var services = splitEnumsToStream(theInput).map(result -> (IConsentService)ConstantConsentService.constantService(result)).toList();
|
||||||
|
myService = withSerialVoting(services);
|
||||||
|
|
||||||
|
var verdict = myService.willSeeResource(mySrd, null, IConsentContextServices.NULL_IMPL);
|
||||||
|
|
||||||
|
assertEquals(theExpectedResult.getStatus(), verdict.getStatus());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static @Nonnull IConsentService buildConsentShouldProcessCanSee(boolean result) {
|
||||||
|
return new IConsentService() {
|
||||||
|
@Override
|
||||||
|
public boolean shouldProcessCanSeeResource(RequestDetails theRequestDetails, IConsentContextServices theContextServices) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user