Skip to content

Commit

Permalink
Bug 565011 rebuild the core of condition expression evaluation
Browse files Browse the repository at this point in the history
 Start covering `conditions.evaluation` with tests.

Signed-off-by: elena.parovyshnaya <[email protected]>
  • Loading branch information
eparovyshnaya committed Jul 9, 2020
1 parent 7bb9af0 commit 1979d63
Show file tree
Hide file tree
Showing 14 changed files with 564 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,10 @@
* at all ({@code Emission.failed()}) and then request either permissions or
* failure details.
* </p>
*
* <p>
* Any implementation must follow the contract defined in
* {@code EmissionContractTest}
* </p>
*/
public interface Emission {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@

import org.eclipse.passage.lic.internal.api.registry.Service;

/**
* Any implementation must follow the contract defined in
* {@code ExpressionEvaluationServiceContractTest}
*/
public interface ExpressionEvaluationService extends Service<ExpressionProtocol> {

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@

import org.eclipse.passage.lic.internal.api.registry.Service;

/**
* An implementation must follow the contract defined in
* {@code ExpressionParsingServiceContractTest}
*/
public interface ExpressionParsingService extends Service<ExpressionProtocol> {

ParsedExpression parsed(String expression) throws ExpressionParsingException;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@
import org.eclipse.passage.lic.internal.api.conditions.evaluation.ParsedExpression;

@SuppressWarnings("restriction")
final class SimpleMapExpression implements ParsedExpression {
public final class SimpleMapExpression implements ParsedExpression {

private final Map<String, String> checks;
private final ExpressionProtocol format;

SimpleMapExpression(ExpressionProtocol format, Map<String, String> checks) {
public SimpleMapExpression(ExpressionProtocol format, Map<String, String> checks) {
Objects.requireNonNull(format);
Objects.requireNonNull(checks);
this.format = format;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
*******************************************************************************/
package org.eclipse.passage.lic.internal.base.conditions.evaluation;

import java.util.Objects;

import org.eclipse.passage.lic.internal.api.conditions.evaluation.ExpressionEvaluationException;
import org.eclipse.passage.lic.internal.api.conditions.evaluation.ExpressionEvaluationService;
import org.eclipse.passage.lic.internal.api.conditions.evaluation.ExpressionProtocol;
Expand All @@ -32,6 +34,9 @@ public ExpressionProtocol id() {
@Override
public void evaluate(ParsedExpression expression, ExpressionTokenAssessmentService assessor)
throws ExpressionEvaluationException {
Objects.requireNonNull(expression);
Objects.requireNonNull(assessor);
verifyProtocol(expression);
SimpleMapExpression map = map(expression);
for (String key : map.keys()) {
boolean passed = equal(key, map.expected(key), assessor);
Expand All @@ -56,16 +61,25 @@ private boolean equal(String key, String value, ExpressionTokenAssessmentService

private SimpleMapExpression map(ParsedExpression expression) throws ExpressionEvaluationException {
if (!SimpleMapExpression.class.isInstance(expression)) {
new ExpressionEvaluationException(String.format(ConditionsEvaluationMessages.getString(//
throw new ExpressionEvaluationException(String.format(ConditionsEvaluationMessages.getString(//
"SimpleMapExpressionEvaluationService.foreign_expression"), // //$NON-NLS-1$
expression.protocol()));
}
SimpleMapExpression map = (SimpleMapExpression) expression;
if (map.keys().isEmpty()) {
new ExpressionEvaluationException(ConditionsEvaluationMessages.getString(//
throw new ExpressionEvaluationException(ConditionsEvaluationMessages.getString(//
"SimpleMapExpressionEvaluationService.no_checks")); //$NON-NLS-1$
}
return map;
}

private void verifyProtocol(ParsedExpression expression) throws ExpressionEvaluationException {
if (!id().equals(expression.protocol())) {
throw new ExpressionEvaluationException(String.format(
ConditionsEvaluationMessages
.getString("SimpleMapExpressionEvaluationService.unexpected_expression_protocol"), //$NON-NLS-1$
expression.protocol(), id()));
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ SimpleMapExpressionEvaluationService.foreign_expression=Expression protocol [%s]
SimpleMapExpressionEvaluationService.no_checks=Expression is invalid: it contains no checks
SimpleMapExpressionEvaluationService.segment_fails_evaluation=Expression fails evaluation (type %s) on segment [%s = %s]
SimpleMapExpressionEvaluationService.evaluation_fails=Expression segment [%s = %s] %s assessment failed with error
SimpleMapExpressionEvaluationService.unexpected_expression_protocol=Unexpected expression protocol [%s] (should be [%s])
AndsProtocolExpressionParseService.invalid_format=Segment [%s] is corrupted. Expected to have key=value structure.
AndsProtocolExpressionParseService.no_checks=Expression [%s] contains no checks. Expected to be of [key=value;...key=value] structure.
BasePermissionEmittingService.failed=Failed to assess expression [%s]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*******************************************************************************
* Copyright (c) 2020 ArSysOp
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* https://www.eclipse.org/legal/epl-2.0/.
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* ArSysOp - initial API and implementation
*******************************************************************************/
package org.eclipse.passage.lic.api.tests.conditions.evaluation;

import org.eclipse.passage.lic.api.tests.fakes.conditions.evaluation.FakePermission;
import org.eclipse.passage.lic.api.tests.fakes.diagnostic.FakeFailureDiagnostic;
import org.eclipse.passage.lic.internal.api.conditions.evaluation.Emission;

@SuppressWarnings("restriction")
public class EmissionImplsContractTest extends EmissionContractTest {

@Override
protected Emission failed() {
return new Emission.Failed(new FakeFailureDiagnostic());
}

@Override
protected Emission successful() {
return new Emission.Successful(new FakePermission());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*******************************************************************************
* Copyright (c) 2020 ArSysOp
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* https://www.eclipse.org/legal/epl-2.0/.
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* ArSysOp - initial API and implementation
*******************************************************************************/
package org.eclipse.passage.lic.api.tests.conditions.evaluation;

import static org.junit.Assert.fail;

import org.eclipse.passage.lic.api.tests.fakes.conditions.evaluation.FakeExpressionTokenAssessmentService;
import org.eclipse.passage.lic.api.tests.fakes.conditions.evaluation.FakeParsedExpression;
import org.eclipse.passage.lic.internal.api.conditions.evaluation.ExpressionEvaluationException;
import org.eclipse.passage.lic.internal.api.conditions.evaluation.ExpressionEvaluationService;
import org.eclipse.passage.lic.internal.api.conditions.evaluation.ExpressionTokenAssessmentService;
import org.eclipse.passage.lic.internal.api.conditions.evaluation.ParsedExpression;
import org.junit.Test;

@SuppressWarnings("restriction")
public abstract class ExpressionEvaluationServiceContractTest {

@Test(expected = NullPointerException.class)
public final void prohibitsNullExpression() {
prohibitsNullArgument(null, new FakeExpressionTokenAssessmentService());
}

@Test(expected = NullPointerException.class)
public final void prohibitsNullAssessor() {
prohibitsNullArgument(new FakeParsedExpression(), null);
}

@Test(expected = ExpressionEvaluationException.class)
public final void canOnlyEvaluateExpressionOfSameProtocl() throws ExpressionEvaluationException {
evaluator().evaluate(new FakeParsedExpression("fake"), //$NON-NLS-1$
new FakeExpressionTokenAssessmentService());
}

private void prohibitsNullArgument(ParsedExpression expression, ExpressionTokenAssessmentService assessor) {
try {
evaluator().evaluate(expression, assessor);
} catch (ExpressionEvaluationException e) {
fail("No evaluation activity is expected to be started for invalid incoming data"); //$NON-NLS-1$
}
}

protected abstract ExpressionEvaluationService evaluator();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*******************************************************************************
* Copyright (c) 2020 ArSysOp
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* https://www.eclipse.org/legal/epl-2.0/.
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* ArSysOp - initial API and implementation
*******************************************************************************/
package org.eclipse.passage.lic.api.tests.conditions.evaluation;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import org.eclipse.passage.lic.internal.api.conditions.evaluation.ExpressionParsingException;
import org.eclipse.passage.lic.internal.api.conditions.evaluation.ExpressionParsingService;
import org.eclipse.passage.lic.internal.api.conditions.evaluation.ParsedExpression;
import org.junit.Test;

@SuppressWarnings("restriction")
public abstract class ExpressionParsingServiceContractTest {

@Test(expected = ExpressionParsingException.class)
public final void blankExpressionCausesFailure() throws ExpressionParsingException {
parser().parsed("\t"); //$NON-NLS-1$
}

@Test(expected = NullPointerException.class)
public final void prohibitsNullExpression() throws ExpressionParsingException {
parser().parsed(null);
}

@Test
public final void producesSameProtocolResult() {
ExpressionParsingService parser = parser();
try {
assertEquals(parser.id(), parser.parsed(validExpression()).protocol());
} catch (ExpressionParsingException e) {
fail("Is not expected to fail on valid data"); //$NON-NLS-1$
}
}

@Test
public final void producesResultOfExpectedType() throws ExpressionParsingException {
assertTrue(resultType().isInstance(parser().parsed(validExpression())));
}

protected abstract ExpressionParsingService parser();

protected abstract String validExpression();

protected abstract Class<? extends ParsedExpression> resultType();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*******************************************************************************
* Copyright (c) 2020 ArSysOp
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* https://www.eclipse.org/legal/epl-2.0/.
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* ArSysOp - initial API and implementation
*******************************************************************************/
package org.eclipse.passage.lic.api.tests.fakes.conditions.evaluation;

import org.eclipse.passage.lic.internal.api.conditions.evaluation.ExpressionProtocol;
import org.eclipse.passage.lic.internal.api.conditions.evaluation.ParsedExpression;

@SuppressWarnings("restriction")
public final class FakeParsedExpression implements ParsedExpression {

private final ExpressionProtocol protocol;

public FakeParsedExpression(ExpressionProtocol protocol) {
this.protocol = protocol;
}

public FakeParsedExpression(String protocol) {
this(new ExpressionProtocol.Of(protocol));
}

public FakeParsedExpression() {
this(new ExpressionProtocol.Default());
}

@Override
public ExpressionProtocol protocol() {
return protocol;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/*******************************************************************************
* Copyright (c) 2020 ArSysOp
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* https://www.eclipse.org/legal/epl-2.0/.
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* ArSysOp - initial API and implementation
*******************************************************************************/
package org.eclipse.passage.lic.internal.base.tests.conditions.evaluation;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;

import org.eclipse.passage.lic.api.tests.conditions.evaluation.ExpressionParsingServiceContractTest;
import org.eclipse.passage.lic.internal.api.conditions.evaluation.ExpressionParsingException;
import org.eclipse.passage.lic.internal.api.conditions.evaluation.ExpressionParsingService;
import org.eclipse.passage.lic.internal.api.conditions.evaluation.ParsedExpression;
import org.eclipse.passage.lic.internal.base.conditions.evaluation.AndsProtocolExpressionParseService;
import org.eclipse.passage.lic.internal.base.conditions.evaluation.SimpleMapExpression;
import org.junit.Test;

@SuppressWarnings("restriction")
public final class AndsProtocolExpressionParseServiceTest extends ExpressionParsingServiceContractTest {

@Test
public void parsesValidData() {
try {
parser().parsed("a=b"); //$NON-NLS-1$
} catch (ExpressionParsingException e) {
fail("Is not expected to fial on valid data"); //$NON-NLS-1$
}
}

@Test
public void pasingIsAccurate() throws ExpressionParsingException {
SimpleMapExpression parsed = (SimpleMapExpression) parser().parsed("k1=v1;k2=*;"); //$NON-NLS-1$
assertEquals("v1", parsed.expected("k1")); //$NON-NLS-1$//$NON-NLS-2$
assertEquals("*", parsed.expected("k2")); //$NON-NLS-1$//$NON-NLS-2$
}

@Test(expected = ExpressionParsingException.class)
public void evenSingleCorruptedSegmentFailsParsing() throws ExpressionParsingException {
parser().parsed("k1=v1;k2;k3=v3"); //$NON-NLS-1$
}

@Test(expected = ExpressionParsingException.class)
public void valueOnlySegmentIsCorrupted() throws ExpressionParsingException {
parser().parsed("k1=v1;=v2;k3=v3"); //$NON-NLS-1$
}

@Test(expected = ExpressionParsingException.class)
public void mediatorOnlySegmentIsCorrupted() throws ExpressionParsingException {
parser().parsed("k1=v1;=;k3=v3"); //$NON-NLS-1$
}

@Test
public void allowsWhiteSpaces() throws ExpressionParsingException {
SimpleMapExpression parsed = (SimpleMapExpression) parser().parsed("k 1=v 1"); //$NON-NLS-1$
assertEquals("v 1", parsed.expected("k 1")); //$NON-NLS-1$//$NON-NLS-2$
}

@Test
public void keysAndValuesAreTrimmed() throws ExpressionParsingException {
SimpleMapExpression parsed = (SimpleMapExpression) parser().parsed(" k\n= v\t"); //$NON-NLS-1$
assertEquals("v", parsed.expected("k")); //$NON-NLS-1$//$NON-NLS-2$
}

@Override
protected ExpressionParsingService parser() {
return new AndsProtocolExpressionParseService();
}

@Override
protected String validExpression() {
return "a=b;c=*;d=1 2"; //$NON-NLS-1$
}

@Override
protected Class<? extends ParsedExpression> resultType() {
return SimpleMapExpression.class;
}

}
Loading

0 comments on commit 1979d63

Please sign in to comment.