/*
* Copyright 2017 Red Hat, Inc. and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.kie.dmn.validation;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.*;
import static org.kie.dmn.validation.DMNValidator.Validation.VALIDATE_COMPILATION;
import static org.kie.dmn.validation.DMNValidator.Validation.VALIDATE_MODEL;
import static org.kie.dmn.validation.DMNValidator.Validation.VALIDATE_SCHEMA;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URISyntaxException;
import java.util.List;
import org.junit.Ignore;
import org.junit.Test;
import org.kie.dmn.api.core.DMNMessage;
import org.kie.dmn.api.core.DMNMessageType;
import org.kie.dmn.api.core.DMNModel;
import org.kie.dmn.api.core.DMNRuntime;
import org.kie.dmn.api.marshalling.v1_1.DMNMarshaller;
import org.kie.dmn.backend.marshalling.v1_1.DMNMarshallerFactory;
import org.kie.dmn.core.DMNInputRuntimeTest;
import org.kie.dmn.core.util.DMNRuntimeUtil;
import org.kie.dmn.model.v1_1.Definitions;
public class ValidatorTest extends AbstractValidatorTest {
@Test
public void testDryRun() {
DMNRuntime runtime = DMNRuntimeUtil.createRuntime( "0001-input-data-string.dmn", DMNInputRuntimeTest.class );
DMNModel dmnModel = runtime.getModel( "https://github.com/kiegroup/kie-dmn", "0001-input-data-string" );
assertThat( dmnModel, notNullValue() );
Definitions definitions = dmnModel.getDefinitions();
assertThat( definitions, notNullValue() );
DMNValidatorFactory.newValidator().validate(definitions);
}
private Definitions utilDefinitions(String filename, String modelName) {
// List<DMNMessage> validateXML;
// try {
// validateXML = validator.validate( new File(this.getClass().getResource(filename).toURI()), DMNValidator.Validation.VALIDATE_SCHEMA );
// assertThat( "using unit test method utilDefinitions must received a XML valid DMN file", validateXML, IsEmptyCollection.empty() );
// } catch (URISyntaxException e) {
// e.printStackTrace();
// fail("Unable for the test suite to locate the file for XML validation.");
// }
DMNMarshaller marshaller = DMNMarshallerFactory.newDefaultMarshaller();
try( InputStreamReader isr = new InputStreamReader( getClass().getResourceAsStream( filename ) ) ) {
Definitions definitions = marshaller.unmarshal( isr );
assertThat( definitions, notNullValue() );
return definitions;
} catch ( IOException e ) {
e.printStackTrace();
fail("Unable for the test suite to locate the file for validation.");
}
return null;
}
@Test
public void testInvalidXml() throws URISyntaxException {
List<DMNMessage> validateXML = validator.validate( new File(this.getClass().getResource( "invalidXml.dmn" ).toURI()), DMNValidator.Validation.VALIDATE_SCHEMA);
assertThat( ValidatorUtil.formatMessages( validateXML ), validateXML.size(), is( 1 ) );
assertThat( validateXML.get( 0 ).toString(), validateXML.get( 0 ).getMessageType(), is( DMNMessageType.FAILED_XML_VALIDATION ) );
}
@Test
public void testINVOCATION_MISSING_EXPR() {
List<DMNMessage> validate = validator.validate( getReader( "INVOCATION_MISSING_EXPR.dmn" ), VALIDATE_SCHEMA, VALIDATE_MODEL, VALIDATE_COMPILATION);
assertThat( ValidatorUtil.formatMessages( validate ), validate.size(), is( 1 ) );
assertThat( validate.get( 0 ).toString(), validate.get( 0 ).getMessageType(), is( DMNMessageType.MISSING_EXPRESSION ) );
}
@Test
public void testNAME_INVALID() {
List<DMNMessage> validate = validator.validate( getReader( "NAME_INVALID.dmn" ), VALIDATE_SCHEMA, VALIDATE_MODEL, VALIDATE_COMPILATION);
assertThat( ValidatorUtil.formatMessages( validate ), validate.size(), is( 1 ) );
assertTrue( validate.stream().anyMatch( p -> p.getMessageType().equals( DMNMessageType.INVALID_NAME ) ) );
}
@Test
public void testNAME_INVALID_bis() {
/* in the file NAME_INVALID_bis.dmn there are 3 invalid "names" but only the one for the Decision node should be reported.
* <definitions id="NAME_INVALID" name="code in list of codes" ...
<decision name="code in list of codes" id="d_GreetingMessage">
<variable name="code in list of codes" typeRef="feel:string"/>
*/
List<DMNMessage> validate = validator.validate( getReader( "NAME_INVALID_bis.dmn" ), VALIDATE_SCHEMA, VALIDATE_MODEL, VALIDATE_COMPILATION);
assertThat( ValidatorUtil.formatMessages( validate ), validate.size(), is( 1 ) );
assertTrue( validate.stream().anyMatch( p -> p.getMessageType().equals( DMNMessageType.INVALID_NAME ) ) );
}
@Test
public void testNAME_INVALID_empty_name() {
List<DMNMessage> validate = validator.validate( getReader( "DROOLS-1447.dmn" ), VALIDATE_SCHEMA, VALIDATE_MODEL, VALIDATE_COMPILATION);
assertThat( ValidatorUtil.formatMessages( validate ), validate.size(), is( 4 ) );
assertTrue( validate.stream().anyMatch( p -> p.getMessageType().equals( DMNMessageType.FAILED_XML_VALIDATION ) ) );
assertTrue( validate.stream().anyMatch( p -> p.getMessageType().equals( DMNMessageType.VARIABLE_NAME_MISMATCH ) ) );
assertTrue( validate.stream().anyMatch( p -> p.getMessageType().equals( DMNMessageType.INVALID_NAME ) && p.getSourceId().equals( "_5e43b55c-888e-443c-b1b9-80e4aa6746bd" ) ) );
assertTrue( validate.stream().anyMatch( p -> p.getMessageType().equals( DMNMessageType.INVALID_NAME ) && p.getSourceId().equals( "_b1e4588e-9ce1-4474-8e4e-48dbcdb7524b" ) ) );
}
@Test
public void testDRGELEM_NOT_UNIQUE() {
List<DMNMessage> validate = validator.validate( getReader( "DRGELEM_NOT_UNIQUE.dmn" ), VALIDATE_SCHEMA, VALIDATE_MODEL, VALIDATE_COMPILATION);
assertThat( ValidatorUtil.formatMessages( validate ), validate.size(), is( 2 ) );
assertTrue( validate.stream().anyMatch( p -> p.getMessageType().equals( DMNMessageType.DUPLICATE_NAME ) ) );
}
@Test
public void testFORMAL_PARAM_DUPLICATED() {
List<DMNMessage> validate = validator.validate( getReader( "FORMAL_PARAM_DUPLICATED.dmn" ), VALIDATE_SCHEMA, VALIDATE_MODEL, VALIDATE_COMPILATION);
assertThat( ValidatorUtil.formatMessages( validate ), validate.size(), is( 3 ) );
assertTrue( validate.stream().anyMatch( p -> p.getMessageType().equals( DMNMessageType.DUPLICATED_PARAM ) ) );
}
@Test
public void testINVOCATION_INCONSISTENT_PARAM_NAMES() {
List<DMNMessage> validate = validator.validate( getReader( "INVOCATION_INCONSISTENT_PARAM_NAMES.dmn" ), VALIDATE_SCHEMA, VALIDATE_MODEL, VALIDATE_COMPILATION);
assertThat( ValidatorUtil.formatMessages( validate ), validate.size(), is( 2 ) );
assertTrue( validate.stream().anyMatch( p -> p.getMessageType().equals( DMNMessageType.PARAMETER_MISMATCH ) ) );
}
@Test @Ignore( "Needs to be improved as invocations can be used to invoke functions node defined in BKMs. E.g., FEEL built in functions, etc.")
public void testINVOCATION_MISSING_TARGET() {
Definitions definitions = utilDefinitions( "INVOCATION_MISSING_TARGET.dmn", "INVOCATION_MISSING_TARGET" );
List<DMNMessage> validate = validator.validate(definitions);
// assertTrue( validate.stream().anyMatch( p -> p.getMessageType().equals( DMNMessageType.INVOCATION_MISSING_TARGET ) ) );
}
@Ignore("known current limitation")
@Test
public void testINVOCATION_MISSING_TARGETRbis() {
Definitions definitions = utilDefinitions( "INVOCATION_MISSING_TARGETbis.dmn", "INVOCATION_MISSING_TARGETbis" );
List<DMNMessage> validate = validator.validate(definitions);
// assertTrue( validate.stream().anyMatch( p -> p.getMessageType().equals( DMNMessageType.INVOCATION_MISSING_TARGET ) ) );
}
@Test
public void testINVOCATION_WRONG_PARAM_COUNT() {
List<DMNMessage> validate = validator.validate( getReader( "INVOCATION_WRONG_PARAM_COUNT.dmn" ), VALIDATE_SCHEMA, VALIDATE_MODEL, VALIDATE_COMPILATION);
assertThat( ValidatorUtil.formatMessages( validate ), validate.size(), is( 3 ) );
assertTrue( validate.stream().anyMatch( p -> p.getMessageType().equals( DMNMessageType.PARAMETER_MISMATCH ) ) );
}
@Test
public void testITEMCOMP_DUPLICATED() {
List<DMNMessage> validate = validator.validate( getReader( "ITEMCOMP_DUPLICATED.dmn" ), VALIDATE_SCHEMA, VALIDATE_MODEL, VALIDATE_COMPILATION);
assertThat( ValidatorUtil.formatMessages( validate ), validate.size(), is( 2 ) );
assertTrue( validate.stream().anyMatch( p -> p.getMessageType().equals( DMNMessageType.DUPLICATED_ITEM_DEF ) ) );
}
@Test
public void testITEMDEF_NOT_UNIQUE() {
List<DMNMessage> validate = validator.validate( getReader( "ITEMDEF_NOT_UNIQUE.dmn" ), VALIDATE_SCHEMA, VALIDATE_MODEL, VALIDATE_COMPILATION);
assertThat( ValidatorUtil.formatMessages( validate ), validate.size(), is( 2 ) );
assertTrue( validate.stream().anyMatch( p -> p.getMessageType().equals( DMNMessageType.DUPLICATED_ITEM_DEF ) ) );
}
@Test
public void testITEMDEF_NOT_UNIQUE_DROOLS_1450() {
// DROOLS-1450
List<DMNMessage> validate = validator.validate( getReader( "ITEMDEF_NOT_UNIQUE_DROOLS-1450.dmn" ), VALIDATE_SCHEMA, VALIDATE_MODEL, VALIDATE_COMPILATION);
assertThat( ValidatorUtil.formatMessages( validate ), validate.size(), is( 0 ) );
}
@Test
public void testRELATION_DUP_COLUMN() {
List<DMNMessage> validate = validator.validate( getReader( "RELATION_DUP_COLUMN.dmn" ), VALIDATE_SCHEMA, VALIDATE_MODEL, VALIDATE_COMPILATION);
assertThat( ValidatorUtil.formatMessages( validate ), validate.size(), is( 2 ) );
assertTrue( validate.stream().anyMatch( p -> p.getMessageType().equals( DMNMessageType.DUPLICATED_RELATION_COLUMN ) ) );
}
@Test
public void testRELATION_ROW_CELL_NOTLITERAL() {
List<DMNMessage> validate = validator.validate( getReader( "RELATION_ROW_CELL_NOTLITERAL.dmn" ), VALIDATE_SCHEMA, VALIDATE_MODEL, VALIDATE_COMPILATION);
assertThat( ValidatorUtil.formatMessages( validate ), validate.size(), is( 2 ) );
assertTrue( validate.stream().anyMatch( p -> p.getMessageType().equals( DMNMessageType.RELATION_CELL_NOT_LITERAL ) ) );
assertTrue( validate.stream().anyMatch( p -> p.getMessageType().equals( DMNMessageType.MISSING_EXPRESSION ) ) );
}
@Test
public void testRELATION_ROW_CELLCOUNTMISMATCH() {
List<DMNMessage> validate = validator.validate( getReader( "RELATION_ROW_CELLCOUNTMISMATCH.dmn" ), VALIDATE_SCHEMA, VALIDATE_MODEL, VALIDATE_COMPILATION);
assertThat( ValidatorUtil.formatMessages( validate ), validate.size(), is( 1 ) );
assertTrue( validate.stream().anyMatch( p -> p.getMessageType().equals( DMNMessageType.RELATION_CELL_COUNT_MISMATCH ) ) );
}
@Test
public void testMortgageRecommender() {
// This file has a gazillion errors. The goal of this test is simply check that the validator itself is not blowing up
// and raising an exception. The errors in the file itself are irrelevant.
List<DMNMessage> validate = validator.validate( getReader( "MortgageRecommender.dmn" ), VALIDATE_SCHEMA, VALIDATE_MODEL, VALIDATE_COMPILATION);
assertThat( ValidatorUtil.formatMessages( validate ), validate.isEmpty(), is( false ) );
}
@Test
public void testREQAUTH_NOT_KNOWLEDGESOURCEbis() {
// DROOLS-1435
List<DMNMessage> validate = validator.validate( getReader( "REQAUTH_NOT_KNOWLEDGESOURCEbis.dmn" ), VALIDATE_SCHEMA, VALIDATE_MODEL, VALIDATE_COMPILATION);
assertThat( ValidatorUtil.formatMessages( validate ), validate.size(), is( 1 ) );
}
@Test
public void testVARIABLE_LEADING_TRAILING_SPACES() {
List<DMNMessage> validate = validator.validate( getReader( "VARIABLE_LEADING_TRAILING_SPACES.dmn" ), VALIDATE_SCHEMA, VALIDATE_MODEL, VALIDATE_COMPILATION);
assertThat( ValidatorUtil.formatMessages( validate ), validate.size(), is( 1 ) );
assertTrue( validate.stream().anyMatch( p -> p.getMessageType().equals( DMNMessageType.INVALID_NAME ) ) );
assertThat( validate.get(0).getSourceId(), is("_dd662d27-7896-42cb-9d14-bd74203bdbec") );
}
@Test
public void testUNKNOWN_VARIABLE() {
List<DMNMessage> validate = validator.validate( getReader( "UNKNOWN_VARIABLE.dmn" ), VALIDATE_SCHEMA, VALIDATE_MODEL, VALIDATE_COMPILATION);
assertThat( ValidatorUtil.formatMessages( validate ), validate.size(), is( 1 ) );
assertTrue( validate.stream().anyMatch( p -> p.getMessageType().equals( DMNMessageType.ERR_COMPILING_FEEL ) ) );
}
@Test
public void testVALIDATION() {
List<DMNMessage> validate = validator.validate( getReader( "validation.dmn" ), VALIDATE_MODEL, VALIDATE_COMPILATION);
assertThat( ValidatorUtil.formatMessages( validate ), validate.size(), is( 5 ) );
assertTrue( validate.stream().anyMatch( p -> p.getMessageType().equals( DMNMessageType.INVALID_NAME ) ) );
assertTrue( validate.stream().anyMatch( p -> p.getMessageType().equals( DMNMessageType.MISSING_TYPE_REF ) ) );
assertTrue( validate.stream().anyMatch( p -> p.getMessageType().equals( DMNMessageType.MISSING_EXPRESSION ) ) );
assertTrue( validate.stream().anyMatch( p -> p.getMessageType().equals( DMNMessageType.ERR_COMPILING_FEEL ) ) );
// on node DTI the `Loan Payment` is of type `tLoanPayment` hence the property is `monthlyAmount`, NOT `amount` as reported in the model FEEL expression: (Loan Payment.amount+...
assertTrue( validate.stream().anyMatch( p -> p.getMessageType().equals( DMNMessageType.ERR_COMPILING_FEEL ) ) );
}
}