package jnpf.elnService.formula;
|
|
import com.fasterxml.jackson.databind.JsonNode;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.node.ArrayNode;
|
import com.fasterxml.jackson.databind.node.BooleanNode;
|
import com.fasterxml.jackson.databind.node.DecimalNode;
|
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
|
import com.fasterxml.jackson.databind.node.NullNode;
|
import com.fasterxml.jackson.databind.node.TextNode;
|
import jnpf.elnEntity.formula.ElnFormulaForms;
|
import jnpf.elnEntity.formula.ElnFormulaVos;
|
import jnpf.elnFormula.FormulaDiagnostic;
|
import jnpf.elnFormula.FormulaLimits;
|
import jnpf.elnService.formula.impl.FormulaPreviewServiceImpl;
|
import jnpf.elnService.formula.impl.FormulaValidationServiceImpl;
|
import org.junit.Before;
|
import org.junit.Test;
|
|
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Field;
|
import java.math.BigDecimal;
|
import java.util.Arrays;
|
import java.util.LinkedHashMap;
|
import java.util.List;
|
import java.util.Map;
|
|
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertNull;
|
import static org.junit.Assert.assertSame;
|
import static org.junit.Assert.assertTrue;
|
|
public class FormulaPreviewServiceTest {
|
|
private FormulaPreviewService service;
|
|
@Before
|
public void setUp() {
|
service = new FormulaPreviewServiceImpl(new FormulaValidationServiceImpl());
|
}
|
|
@Test
|
public void exposesFixedFunctionCatalogAndFullValidation() {
|
assertEquals(37, service.functions().size());
|
assertEquals("ABS", service.functions().get(0).getCode());
|
assertEquals("DECIMAL", service.functions().get(0).getReturnType());
|
assertEquals("DYNAMIC", service.functions().get(5).getReturnType());
|
assertEquals("DYNAMIC", service.functions().get(6).getReturnType());
|
assertEquals("BOOLEAN", service.functions().get(7).getReturnType());
|
assertEquals("LOOKUP_LINEAR", service.functions().get(17).getCode());
|
assertEquals("DECIMAL", service.functions().get(17).getReturnType());
|
|
ElnFormulaForms.Validate form = validateForm("amount + 1", "DECIMAL",
|
slot("amount", "金额", "DECIMAL", true));
|
FormulaValidationService.ValidationResult result = service.validate(form);
|
|
assertFalse(result.hasErrors());
|
assertEquals("\\text{金额} + 1", result.getLatex());
|
}
|
|
@Test
|
public void dependsOnlyOnValidationAndInMemoryFormulaEngine() {
|
for (Field field : FormulaPreviewServiceImpl.class.getDeclaredFields()) {
|
assertNotPersistenceOrAuditDependency(field.getType());
|
}
|
for (Constructor<?> constructor : FormulaPreviewServiceImpl.class.getDeclaredConstructors()) {
|
for (Class<?> parameterType : constructor.getParameterTypes()) {
|
assertNotPersistenceOrAuditDependency(parameterType);
|
}
|
}
|
}
|
|
@Test
|
public void validationAndPreviewDoNotMutateOrRetainRequestData() {
|
ElnFormulaForms.Validate validation = validateForm(
|
"amount + 1", "DECIMAL", slot("amount", "金额", "DECIMAL", true));
|
String validationExpression = validation.getBiaodashi();
|
List<ElnFormulaForms.Parameter> validationParameters = validation.getParameters();
|
JsonNode validationSlots = snapshotSlots(validationParameters);
|
|
service.validate(validation);
|
|
assertEquals(validationExpression, validation.getBiaodashi());
|
assertSame(validationParameters, validation.getParameters());
|
assertEquals(validationSlots, snapshotSlots(validation.getParameters()));
|
|
ElnFormulaForms.Preview preview = previewForm(
|
"amount + SUM(values)", "DECIMAL",
|
slot("amount", "金额", "DECIMAL", true),
|
slot("values", "结果集", "DECIMAL_LIST", true));
|
preview.getInputs().put("amount", new TextNode("1.25"));
|
ArrayNode values = JsonNodeFactory.instance.arrayNode();
|
values.add(new BigDecimal("1"));
|
values.add(new BigDecimal("2"));
|
preview.getInputs().put("values", values);
|
String previewExpression = preview.getBiaodashi();
|
List<ElnFormulaForms.Parameter> previewParameters = preview.getParameters();
|
JsonNode previewSlots = snapshotSlots(previewParameters);
|
Map<String, JsonNode> previewInputs = preview.getInputs();
|
Map<String, JsonNode> inputSnapshot = copyInputs(previewInputs);
|
|
assertEquals(new BigDecimal("4.25"), service.preview(preview).getRawResult());
|
|
assertEquals(previewExpression, preview.getBiaodashi());
|
assertSame(previewParameters, preview.getParameters());
|
assertEquals(previewSlots, snapshotSlots(preview.getParameters()));
|
assertSame(previewInputs, preview.getInputs());
|
assertEquals(inputSnapshot, preview.getInputs());
|
|
ElnFormulaForms.Preview next = previewForm(
|
"amount + SUM(values)", "DECIMAL",
|
slot("amount", "金额", "DECIMAL", true),
|
slot("values", "结果集", "DECIMAL_LIST", true));
|
next.getInputs().put("amount", new TextNode("7"));
|
ArrayNode nextValues = JsonNodeFactory.instance.arrayNode();
|
nextValues.add(new BigDecimal("3"));
|
next.getInputs().put("values", nextValues);
|
|
assertEquals(new BigDecimal("10"), service.preview(next).getRawResult());
|
assertEquals(inputSnapshot, preview.getInputs());
|
}
|
|
@Test
|
public void previewsStrictInputsAndAppliesConfiguredRounding() {
|
ElnFormulaForms.Preview form = previewForm(
|
"amount + SUM(values)", "DECIMAL",
|
slot("amount", "金额", "DECIMAL", true),
|
slot("values", "结果集", "DECIMAL_LIST", true));
|
form.setXiuyueXiaoshuWei(2);
|
form.setXiuyueMoshi("HALF_UP");
|
form.getInputs().put("amount", new TextNode("1.005"));
|
ArrayNode values = JsonNodeFactory.instance.arrayNode();
|
values.add(new BigDecimal("1.11"));
|
values.add("2.22");
|
form.getInputs().put("values", values);
|
|
ElnFormulaVos.Preview result = service.preview(form);
|
|
assertEquals("SUCCESS", result.getStatus());
|
assertEquals(new BigDecimal("4.335"), result.getRawResult());
|
assertEquals(new BigDecimal("4.34"), result.getRoundedResult());
|
assertTrue(result.getDiagnostics().isEmpty());
|
assertTrue(result.getLatex().contains("金额"));
|
}
|
|
@Test
|
public void acceptsOnlyExactTextAndBooleanJsonTypes() {
|
ElnFormulaForms.Preview text = previewForm("label", "TEXT",
|
slot("label", "标签", "TEXT", true));
|
text.getInputs().put("label", new TextNode("合格"));
|
assertEquals("合格", service.preview(text).getRawResult());
|
|
ElnFormulaForms.Preview bool = previewForm("flag", "BOOLEAN",
|
slot("flag", "标志", "BOOLEAN", true));
|
bool.getInputs().put("flag", BooleanNode.TRUE);
|
assertEquals(Boolean.TRUE, service.preview(bool).getRawResult());
|
|
text.getInputs().put("label", BooleanNode.TRUE);
|
assertError(service.preview(text), "INVALID_INPUT_TYPE");
|
bool.getInputs().put("flag", new TextNode("true"));
|
assertError(service.preview(bool), "INVALID_INPUT_TYPE");
|
}
|
|
@Test
|
public void rejectsUnknownScientificNonFiniteAndOversizedInputs() {
|
ElnFormulaForms.Preview decimal = previewForm("amount", "DECIMAL",
|
slot("amount", "金额", "DECIMAL", true));
|
decimal.getInputs().put("other", DecimalNode.valueOf(BigDecimal.ONE));
|
assertError(service.preview(decimal), "UNKNOWN_INPUT");
|
|
decimal.getInputs().clear();
|
decimal.getInputs().put("amount", new TextNode("1e3"));
|
assertError(service.preview(decimal), "INVALID_DECIMAL_INPUT");
|
|
decimal.getInputs().put("amount", JsonNodeFactory.instance.numberNode(Double.NaN));
|
assertError(service.preview(decimal), "INVALID_DECIMAL_INPUT");
|
|
decimal.getInputs().put("amount", JsonNodeFactory.instance.numberNode(Double.POSITIVE_INFINITY));
|
assertError(service.preview(decimal), "INVALID_DECIMAL_INPUT");
|
|
ElnFormulaForms.Preview list = previewForm("SUM(values)", "DECIMAL",
|
slot("values", "结果集", "DECIMAL_LIST", true));
|
ArrayNode values = JsonNodeFactory.instance.arrayNode();
|
for (int i = 0; i < 1001; i++) {
|
values.add(i);
|
}
|
list.getInputs().put("values", values);
|
assertError(service.preview(list), "LIST_ITEM_LIMIT_EXCEEDED");
|
}
|
|
@Test
|
public void rejectsScientificJsonNumberAfterRequestDeserialization() throws Exception {
|
String json = "{\"biaodashi\":\"amount\",\"jieguoLeixing\":\"DECIMAL\","
|
+ "\"parameters\":[{\"canshuBianma\":\"amount\","
|
+ "\"canshuMingcheng\":\"金额\",\"shujuLeixing\":\"DECIMAL\","
|
+ "\"shifouBitian\":1}],\"inputs\":{\"amount\":1e3}}";
|
|
ElnFormulaForms.Preview form = new ObjectMapper()
|
.readValue(json, ElnFormulaForms.Preview.class);
|
|
assertError(service.preview(form), "INVALID_DECIMAL_INPUT");
|
}
|
|
@Test
|
public void rejectsScientificListItemsAfterRequestDeserialization() throws Exception {
|
String json = "{\"biaodashi\":\"SUM(values)\",\"jieguoLeixing\":\"DECIMAL\","
|
+ "\"parameters\":[{\"canshuBianma\":\"values\","
|
+ "\"canshuMingcheng\":\"结果集\",\"shujuLeixing\":\"DECIMAL_LIST\","
|
+ "\"shifouBitian\":1}],\"inputs\":{\"values\":[1,1e3,\"2e2\"]}}";
|
|
ElnFormulaForms.Preview form = new ObjectMapper()
|
.readValue(json, ElnFormulaForms.Preview.class);
|
|
assertError(service.preview(form), "INVALID_DECIMAL_INPUT");
|
|
ElnFormulaForms.Preview stringItem = new ObjectMapper().readValue(
|
json.replace("[1,1e3,\"2e2\"]", "[1,\"2e2\"]"),
|
ElnFormulaForms.Preview.class);
|
assertError(service.preview(stringItem), "INVALID_DECIMAL_INPUT");
|
}
|
|
@Test
|
public void rejectsNegativeExponentJsonNumbersAfterRequestDeserialization() throws Exception {
|
String scalarJson = "{\"biaodashi\":\"amount\",\"jieguoLeixing\":\"DECIMAL\","
|
+ "\"parameters\":[{\"canshuBianma\":\"amount\","
|
+ "\"canshuMingcheng\":\"金额\",\"shujuLeixing\":\"DECIMAL\","
|
+ "\"shifouBitian\":1}],\"inputs\":{\"amount\":1E-3}}";
|
String listJson = "{\"biaodashi\":\"SUM(values)\",\"jieguoLeixing\":\"DECIMAL\","
|
+ "\"parameters\":[{\"canshuBianma\":\"values\","
|
+ "\"canshuMingcheng\":\"结果集\",\"shujuLeixing\":\"DECIMAL_LIST\","
|
+ "\"shifouBitian\":1}],\"inputs\":{\"values\":[1,1E-3]}}";
|
|
ObjectMapper mapper = new ObjectMapper();
|
assertError(service.preview(mapper.readValue(scalarJson, ElnFormulaForms.Preview.class)),
|
"INVALID_DECIMAL_INPUT");
|
assertError(service.preview(mapper.readValue(listJson, ElnFormulaForms.Preview.class)),
|
"INVALID_DECIMAL_INPUT");
|
}
|
|
@Test
|
public void acceptsPlainJsonNumbersAndStringsAfterRequestDeserialization() throws Exception {
|
String json = "{\"biaodashi\":\"amount + SUM(values)\","
|
+ "\"jieguoLeixing\":\"DECIMAL\",\"parameters\":["
|
+ "{\"canshuBianma\":\"amount\",\"canshuMingcheng\":\"金额\","
|
+ "\"shujuLeixing\":\"DECIMAL\",\"shifouBitian\":1},"
|
+ "{\"canshuBianma\":\"values\",\"canshuMingcheng\":\"结果集\","
|
+ "\"shujuLeixing\":\"DECIMAL_LIST\",\"shifouBitian\":1}],"
|
+ "\"inputs\":{\"amount\":1.25,\"values\":[1,2.5,\"3.25\"]}}";
|
|
ElnFormulaForms.Preview form = new ObjectMapper()
|
.readValue(json, ElnFormulaForms.Preview.class);
|
|
assertEquals(new BigDecimal("8.00"), service.preview(form).getRawResult());
|
|
ElnFormulaForms.Preview plainSmall = new ObjectMapper().readValue(
|
json.replace("1.25", "0.001"), ElnFormulaForms.Preview.class);
|
assertEquals(new BigDecimal("6.751"), service.preview(plainSmall).getRawResult());
|
}
|
|
@Test
|
public void acceptsLargeFinitePlainJsonNumberLikeEquivalentString() throws Exception {
|
String digits = repeat('9', 309);
|
String prefix = "{\"biaodashi\":\"amount\",\"jieguoLeixing\":\"DECIMAL\","
|
+ "\"parameters\":[{\"canshuBianma\":\"amount\","
|
+ "\"canshuMingcheng\":\"金额\",\"shujuLeixing\":\"DECIMAL\","
|
+ "\"shifouBitian\":1}],\"inputs\":{\"amount\":";
|
ObjectMapper mapper = new ObjectMapper();
|
ElnFormulaVos.Preview numberResult = service.preview(mapper.readValue(
|
prefix + digits + "}}", ElnFormulaForms.Preview.class));
|
ElnFormulaVos.Preview stringResult = service.preview(mapper.readValue(
|
prefix + "\"" + digits + "\"}}", ElnFormulaForms.Preview.class));
|
|
assertEquals("SUCCESS", numberResult.getStatus());
|
assertEquals("SUCCESS", stringResult.getStatus());
|
assertEquals(stringResult.getRawResult(), numberResult.getRawResult());
|
}
|
|
@Test
|
public void rejectsDecimalLexemesLongerThanExpressionLimit() {
|
String digits = repeat('7', FormulaLimits.DEFAULTS.getMaxExpressionLength() + 1);
|
ElnFormulaForms.Preview scalar = previewForm("amount", "DECIMAL",
|
slot("amount", "金额", "DECIMAL", true));
|
|
scalar.getInputs().put("amount", new TextNode(digits));
|
assertError(service.preview(scalar), "DECIMAL_INPUT_TOO_LONG");
|
|
scalar.getInputs().put("amount", DecimalNode.valueOf(new BigDecimal(digits)));
|
assertError(service.preview(scalar), "DECIMAL_INPUT_TOO_LONG");
|
|
ElnFormulaForms.Preview list = previewForm("SUM(values)", "DECIMAL",
|
slot("values", "结果集", "DECIMAL_LIST", true));
|
ArrayNode values = JsonNodeFactory.instance.arrayNode();
|
values.add(digits);
|
list.getInputs().put("values", values);
|
assertError(service.preview(list), "DECIMAL_INPUT_TOO_LONG");
|
}
|
|
@Test
|
public void doesNotTurnJsonNumberIntoTextDuringRequestDeserialization() throws Exception {
|
String json = "{\"biaodashi\":\"label\",\"jieguoLeixing\":\"TEXT\","
|
+ "\"parameters\":[{\"canshuBianma\":\"label\","
|
+ "\"canshuMingcheng\":\"标签\",\"shujuLeixing\":\"TEXT\","
|
+ "\"shifouBitian\":1}],\"inputs\":{\"label\":1.25}}";
|
|
ElnFormulaForms.Preview form = new ObjectMapper()
|
.readValue(json, ElnFormulaForms.Preview.class);
|
|
assertError(service.preview(form), "INVALID_INPUT_TYPE");
|
}
|
|
@Test
|
public void reportsRequiredNullAndBlankInputsAsMissing() {
|
ElnFormulaForms.Preview form = previewForm("amount", "DECIMAL",
|
slot("amount", "金额", "DECIMAL", true));
|
assertMissing(service.preview(form), "amount");
|
|
form.getInputs().put("amount", NullNode.instance);
|
assertMissing(service.preview(form), "amount");
|
|
form.getInputs().put("amount", new TextNode(""));
|
assertMissing(service.preview(form), "amount");
|
}
|
|
@Test
|
public void optionalMissingInputCanBeHandledByCoalesceOrShortCircuit() {
|
ElnFormulaForms.Preview coalesce = previewForm("COALESCE(amount, 2)", "DECIMAL",
|
slot("amount", "金额", "DECIMAL", false));
|
assertEquals(new BigDecimal("2"), service.preview(coalesce).getRawResult());
|
|
ElnFormulaForms.Preview branch = previewForm("IF(false, amount, 3)", "DECIMAL",
|
slot("amount", "金额", "DECIMAL", false));
|
assertEquals(new BigDecimal("3"), service.preview(branch).getRawResult());
|
}
|
|
@Test
|
public void reportsOptionalNullWhenEvaluatedOrReturned() {
|
ElnFormulaForms.Preview evaluated = previewForm("amount + 1", "DECIMAL",
|
slot("amount", "金额", "DECIMAL", false));
|
assertMissing(service.preview(evaluated), "amount");
|
|
ElnFormulaForms.Preview returned = previewForm("COALESCE(amount)", "DECIMAL",
|
slot("amount", "金额", "DECIMAL", false));
|
assertMissing(service.preview(returned), "结果为空");
|
}
|
|
@Test
|
public void reportsOnlyActuallyAccessedOptionalMissingInputs() {
|
ElnFormulaForms.Preview form = previewForm("amount + 1", "DECIMAL",
|
slot("amount", "金额", "DECIMAL", false),
|
slot("unused", "未使用", "DECIMAL", false));
|
|
ElnFormulaVos.Preview result = service.preview(form);
|
|
assertEquals("MISSING_INPUT", result.getStatus());
|
int missingDiagnostics = 0;
|
for (ElnFormulaVos.Diagnostic diagnostic : result.getDiagnostics()) {
|
if ("MISSING_INPUT".equals(diagnostic.getCode())) {
|
missingDiagnostics++;
|
assertTrue(diagnostic.getMessage().contains("amount"));
|
assertFalse(diagnostic.getMessage().contains("unused"));
|
}
|
}
|
assertEquals(1, missingDiagnostics);
|
}
|
|
@Test
|
public void reportsOnlyRightMissingInputWhenLeftCoalesceHasFallback() {
|
ElnFormulaForms.Preview form = previewForm("COALESCE(a, 1) + b", "DECIMAL",
|
slot("a", "参数 A", "DECIMAL", false),
|
slot("b", "参数 B", "DECIMAL", false));
|
assertOnlyMissing(service.preview(form), "b", "a");
|
}
|
|
@Test
|
public void reportsOnlyLeftMissingInputWhenRightCoalesceHasFallback() {
|
ElnFormulaForms.Preview form = previewForm("a + COALESCE(b, 1)", "DECIMAL",
|
slot("a", "参数 A", "DECIMAL", false),
|
slot("b", "参数 B", "DECIMAL", false));
|
assertOnlyMissing(service.preview(form), "a", "b");
|
}
|
|
@Test
|
public void rejectsInvalidRequiredFlagsDuringValidation() {
|
for (Integer flag : Arrays.asList(null, 2, -1)) {
|
ElnFormulaForms.Parameter parameter = slot("amount", "金额", "DECIMAL", true);
|
parameter.setShifouBitian(flag);
|
FormulaValidationService.ValidationResult result = service.validate(
|
validateForm("amount + 1", "DECIMAL", parameter));
|
|
assertValidationDiagnostic(result, "INVALID_PARAMETER_REQUIRED_FLAG");
|
assertNull(result.getLatex());
|
}
|
}
|
|
@Test
|
public void rejectsInvalidRequiredFlagsBeforePreviewEvaluation() {
|
for (Integer flag : Arrays.asList(null, 2, -1)) {
|
ElnFormulaForms.Parameter parameter = slot("amount", "金额", "DECIMAL", true);
|
parameter.setShifouBitian(flag);
|
ElnFormulaForms.Preview form = previewForm(
|
"COALESCE(amount, 2)", "DECIMAL", parameter);
|
|
ElnFormulaVos.Preview result = service.preview(form);
|
assertError(result, "INVALID_PARAMETER_REQUIRED_FLAG");
|
assertNull(result.getLatex());
|
}
|
}
|
|
@Test
|
public void stopsAtFullValidationBeforeInspectingInputs() {
|
ElnFormulaForms.Preview form = previewForm("unknown +", "DECIMAL");
|
form.getInputs().put("unexpected", DecimalNode.valueOf(BigDecimal.ONE));
|
|
ElnFormulaVos.Preview result = service.preview(form);
|
|
assertEquals("ERROR", result.getStatus());
|
assertDiagnostic(result.getDiagnostics(), "SYNTAX_ERROR");
|
assertFalse(hasDiagnostic(result.getDiagnostics(), "UNKNOWN_INPUT"));
|
assertNull(result.getRawResult());
|
assertNull(result.getRoundedResult());
|
}
|
|
private static ElnFormulaForms.Validate validateForm(String expression, String resultType,
|
ElnFormulaForms.Parameter... slots) {
|
ElnFormulaForms.Validate form = new ElnFormulaForms.Validate();
|
setRule(form, expression, resultType, slots);
|
return form;
|
}
|
|
private static ElnFormulaForms.Preview previewForm(String expression, String resultType,
|
ElnFormulaForms.Parameter... slots) {
|
ElnFormulaForms.Preview form = new ElnFormulaForms.Preview();
|
setRule(form, expression, resultType, slots);
|
form.setInputs(new LinkedHashMap<String, JsonNode>());
|
return form;
|
}
|
|
private static void setRule(ElnFormulaForms.VersionRule form, String expression,
|
String resultType, ElnFormulaForms.Parameter... slots) {
|
form.setBiaodashi(expression);
|
form.setJieguoLeixing(resultType);
|
form.setParameters(Arrays.asList(slots));
|
}
|
|
private static ElnFormulaForms.Parameter slot(String code, String name, String type,
|
boolean required) {
|
ElnFormulaForms.Parameter slot = new ElnFormulaForms.Parameter();
|
slot.setCanshuBianma(code);
|
slot.setCanshuMingcheng(name);
|
slot.setShujuLeixing(type);
|
slot.setShifouBitian(required ? 1 : 0);
|
return slot;
|
}
|
|
private static JsonNode snapshotSlots(List<ElnFormulaForms.Parameter> slots) {
|
return new ObjectMapper().valueToTree(slots);
|
}
|
|
private static Map<String, JsonNode> copyInputs(Map<String, JsonNode> inputs) {
|
Map<String, JsonNode> copy = new LinkedHashMap<>();
|
for (Map.Entry<String, JsonNode> entry : inputs.entrySet()) {
|
copy.put(entry.getKey(), entry.getValue() == null ? null : entry.getValue().deepCopy());
|
}
|
return copy;
|
}
|
|
private static String repeat(char value, int count) {
|
char[] values = new char[count];
|
Arrays.fill(values, value);
|
return new String(values);
|
}
|
|
private static void assertNotPersistenceOrAuditDependency(Class<?> type) {
|
String typeName = type.getName();
|
assertFalse("不允许持久化或审计依赖: " + typeName,
|
typeName.contains("elnMapper")
|
|| typeName.contains("BaseMapper")
|
|| typeName.contains("AuditClient")
|
|| typeName.contains("CatalogService"));
|
}
|
|
private static void assertError(ElnFormulaVos.Preview result, String diagnosticCode) {
|
assertEquals("ERROR", result.getStatus());
|
assertNull(result.getRawResult());
|
assertNull(result.getRoundedResult());
|
assertDiagnostic(result.getDiagnostics(), diagnosticCode);
|
}
|
|
private static void assertMissing(ElnFormulaVos.Preview result, String expectedText) {
|
assertEquals("MISSING_INPUT", result.getStatus());
|
assertNull(result.getRawResult());
|
assertNull(result.getRoundedResult());
|
for (ElnFormulaVos.Diagnostic diagnostic : result.getDiagnostics()) {
|
if (diagnostic.getMessage().contains(expectedText)) {
|
return;
|
}
|
}
|
throw new AssertionError("缺少包含文本的诊断: " + expectedText);
|
}
|
|
private static void assertOnlyMissing(ElnFormulaVos.Preview result, String expectedCode,
|
String unexpectedCode) {
|
assertEquals("MISSING_INPUT", result.getStatus());
|
int missingDiagnostics = 0;
|
for (ElnFormulaVos.Diagnostic diagnostic : result.getDiagnostics()) {
|
if ("MISSING_INPUT".equals(diagnostic.getCode())) {
|
missingDiagnostics++;
|
assertTrue(diagnostic.getMessage().contains(expectedCode));
|
assertFalse(diagnostic.getMessage().contains(unexpectedCode));
|
}
|
}
|
assertEquals(1, missingDiagnostics);
|
}
|
|
private static void assertDiagnostic(List<ElnFormulaVos.Diagnostic> diagnostics, String code) {
|
assertTrue("缺少诊断 " + code, hasDiagnostic(diagnostics, code));
|
}
|
|
private static void assertValidationDiagnostic(
|
FormulaValidationService.ValidationResult result, String code) {
|
for (FormulaDiagnostic diagnostic : result.getDiagnostics()) {
|
if (code.equals(diagnostic.getCode())) {
|
return;
|
}
|
}
|
throw new AssertionError("缺少诊断 " + code);
|
}
|
|
private static boolean hasDiagnostic(List<ElnFormulaVos.Diagnostic> diagnostics, String code) {
|
for (ElnFormulaVos.Diagnostic diagnostic : diagnostics) {
|
if (code.equals(diagnostic.getCode())) {
|
return true;
|
}
|
}
|
return false;
|
}
|
}
|