From bf322937206e15800ea17186f55344b2b0151ea5 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 16 Nov 2023 18:02:03 +0100 Subject: [PATCH] [KIE-686] fix peer update propagation for FromNode (#5584) (#21) (#22) * [KIE-686] fix peer update propagation for FromNode * Update drools-test-coverage/test-compiler-integration/src/test/java/org/drools/compiler/integrationtests/UnexpectedLoopTest.java * Fixed for Java 8 compatibility --------- Co-authored-by: Toshiya Kobayashi Co-authored-by: Mario Fusco --- .../drools/core/phreak/SegmentPropagator.java | 4 +- .../integrationtests/UnexpectedLoopTest.java | 77 +++++++++++++++++++ .../integrationtests/model/CalcFact.java | 34 ++++++++ .../compiler/integrationtests/model/Item.java | 25 ++++++ .../integrationtests/model/RecordFact.java | 34 ++++++++ .../integrationtests/joinFromFrom.drl | 35 +++++++++ 6 files changed, 207 insertions(+), 2 deletions(-) create mode 100644 drools-test-coverage/test-compiler-integration/src/test/java/org/drools/compiler/integrationtests/UnexpectedLoopTest.java create mode 100644 drools-test-coverage/test-compiler-integration/src/test/java/org/drools/compiler/integrationtests/model/CalcFact.java create mode 100644 drools-test-coverage/test-compiler-integration/src/test/java/org/drools/compiler/integrationtests/model/Item.java create mode 100644 drools-test-coverage/test-compiler-integration/src/test/java/org/drools/compiler/integrationtests/model/RecordFact.java create mode 100644 drools-test-coverage/test-compiler-integration/src/test/resources/org/drools/compiler/integrationtests/joinFromFrom.drl diff --git a/drools-core/src/main/java/org/drools/core/phreak/SegmentPropagator.java b/drools-core/src/main/java/org/drools/core/phreak/SegmentPropagator.java index 2e4c7e7f080..db28f0e4248 100644 --- a/drools-core/src/main/java/org/drools/core/phreak/SegmentPropagator.java +++ b/drools-core/src/main/java/org/drools/core/phreak/SegmentPropagator.java @@ -27,7 +27,7 @@ import static org.drools.core.phreak.AddRemoveRule.forceFlushLeftTuple; import static org.drools.core.phreak.AddRemoveRule.forceFlushWhenRiaNode; -import static org.drools.core.reteoo.NodeTypeEnums.hasNodeMemory; +import static org.drools.core.reteoo.NodeTypeEnums.AccumulateNode; public class SegmentPropagator { @@ -131,7 +131,7 @@ private static void updateChildLeftTupleDuringInsert(LeftTuple childLeftTuple, T break; default: // no clash, so just add - if ( hasNodeMemory( childLeftTuple.getTupleSink() ) ) { + if ( childLeftTuple.getTupleSink().getType() == AccumulateNode ) { trgLeftTuples.addInsert(childLeftTuple); } else { trgLeftTuples.addUpdate(childLeftTuple); diff --git a/drools-test-coverage/test-compiler-integration/src/test/java/org/drools/compiler/integrationtests/UnexpectedLoopTest.java b/drools-test-coverage/test-compiler-integration/src/test/java/org/drools/compiler/integrationtests/UnexpectedLoopTest.java new file mode 100644 index 00000000000..e68ba627eb6 --- /dev/null +++ b/drools-test-coverage/test-compiler-integration/src/test/java/org/drools/compiler/integrationtests/UnexpectedLoopTest.java @@ -0,0 +1,77 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.drools.compiler.integrationtests; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + +import org.drools.compiler.integrationtests.model.CalcFact; +import org.drools.compiler.integrationtests.model.Item; +import org.drools.compiler.integrationtests.model.RecordFact; +import org.drools.testcoverage.common.util.KieBaseTestConfiguration; +import org.drools.testcoverage.common.util.KieBaseUtil; +import org.drools.testcoverage.common.util.TestParametersUtil; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.kie.api.KieBase; +import org.kie.api.runtime.KieSession; + +import static org.assertj.core.api.Assertions.assertThat; + +@RunWith(Parameterized.class) +public class UnexpectedLoopTest { + + private final KieBaseTestConfiguration kieBaseTestConfiguration; + + public UnexpectedLoopTest(final KieBaseTestConfiguration kieBaseTestConfiguration) { + this.kieBaseTestConfiguration = kieBaseTestConfiguration; + } + + @Parameterized.Parameters(name = "KieBase type={0}") + public static Collection getParameters() { + return TestParametersUtil.getKieBaseCloudConfigurations(true); + } + + @Test + public void joinFromFromPeerUpdate_shouldNotLoop() { + + final KieBase kieBase = KieBaseUtil.getKieBaseFromClasspathResources(getClass(), kieBaseTestConfiguration, + "org/drools/compiler/integrationtests/joinFromFrom.drl"); + final KieSession ksession = kieBase.newKieSession(); + try { + RecordFact record1 = new RecordFact(null, 0); + Item item1 = new Item(null); + CalcFact calcFact = new CalcFact(new ArrayList<>(Arrays.asList(item1)), 4144); + + ksession.insert("test"); + ksession.insert(record1); + ksession.insert(item1); + ksession.insert(calcFact); + + int fired = ksession.fireAllRules(10); + + assertThat(fired).as("Unexpected loop detected. Expects firing R2 once").isEqualTo(1); + } finally { + ksession.dispose(); + } + } +} diff --git a/drools-test-coverage/test-compiler-integration/src/test/java/org/drools/compiler/integrationtests/model/CalcFact.java b/drools-test-coverage/test-compiler-integration/src/test/java/org/drools/compiler/integrationtests/model/CalcFact.java new file mode 100644 index 00000000000..47afd6f718d --- /dev/null +++ b/drools-test-coverage/test-compiler-integration/src/test/java/org/drools/compiler/integrationtests/model/CalcFact.java @@ -0,0 +1,34 @@ +package org.drools.compiler.integrationtests.model; + +import java.util.List; + +public class CalcFact { + + private List itemList; + private int lineNumber; + + public CalcFact(List itemList, int lineNumber) { + this.itemList = itemList; + this.lineNumber = lineNumber; + } + + public List getItemList() { + return itemList; + } + + public void setItemList(List itemList) { + this.itemList = itemList; + } + + public int getLineNumber() { + return lineNumber; + } + + @Override + public String toString() { + return "CalcFact{" + + "itemList=" + itemList + + ", lineNumber=" + lineNumber + + '}'; + } +} diff --git a/drools-test-coverage/test-compiler-integration/src/test/java/org/drools/compiler/integrationtests/model/Item.java b/drools-test-coverage/test-compiler-integration/src/test/java/org/drools/compiler/integrationtests/model/Item.java new file mode 100644 index 00000000000..665fc8b7b01 --- /dev/null +++ b/drools-test-coverage/test-compiler-integration/src/test/java/org/drools/compiler/integrationtests/model/Item.java @@ -0,0 +1,25 @@ +package org.drools.compiler.integrationtests.model; + +public class Item { + + private String decomposedPointFlag; + + public Item(String decomposedPointFlag) { + this.decomposedPointFlag = decomposedPointFlag; + } + + public String getDecomposedPointFlag() { + return decomposedPointFlag; + } + + public void setDecomposedPointFlag(String decomposedPointFlag) { + this.decomposedPointFlag = decomposedPointFlag; + } + + @Override + public String toString() { + return "Item{" + + "pointFlag='" + decomposedPointFlag + '\'' + + '}'; + } +} diff --git a/drools-test-coverage/test-compiler-integration/src/test/java/org/drools/compiler/integrationtests/model/RecordFact.java b/drools-test-coverage/test-compiler-integration/src/test/java/org/drools/compiler/integrationtests/model/RecordFact.java new file mode 100644 index 00000000000..0338cc46cf9 --- /dev/null +++ b/drools-test-coverage/test-compiler-integration/src/test/java/org/drools/compiler/integrationtests/model/RecordFact.java @@ -0,0 +1,34 @@ +package org.drools.compiler.integrationtests.model; + +import java.math.BigDecimal; + +public class RecordFact { + + private BigDecimal decomposedPoint; + private int lineNumber; + + public RecordFact(BigDecimal decomposedPoint, int lineNumber) { + this.decomposedPoint = decomposedPoint; + this.lineNumber = lineNumber; + } + + public BigDecimal getDecomposedPoint() { + return decomposedPoint; + } + + public void setDecomposedPoint(BigDecimal decomposedPoint) { + this.decomposedPoint = decomposedPoint; + } + + public int getLineNumber() { + return lineNumber; + } + + @Override + public String toString() { + return "RecordFact{" + + ", decomposedPoint=" + decomposedPoint + + ", lineNumber=" + lineNumber + + '}'; + } +} diff --git a/drools-test-coverage/test-compiler-integration/src/test/resources/org/drools/compiler/integrationtests/joinFromFrom.drl b/drools-test-coverage/test-compiler-integration/src/test/resources/org/drools/compiler/integrationtests/joinFromFrom.drl new file mode 100644 index 00000000000..329fe0efa56 --- /dev/null +++ b/drools-test-coverage/test-compiler-integration/src/test/resources/org/drools/compiler/integrationtests/joinFromFrom.drl @@ -0,0 +1,35 @@ +package org.drools.compiler.integrationtests; + +import org.drools.compiler.integrationtests.model.CalcFact; +import org.drools.compiler.integrationtests.model.Item; +import org.drools.compiler.integrationtests.model.RecordFact; + +dialect "mvel" + +rule R1 + when + String() + CalcFact( $lineNumber : lineNumber, $itemList : itemList ) + Integer() + then +end + +rule R2 + when + String() + $fact : CalcFact( $itemList : itemList ) + $item : Item( decomposedPointFlag == null ) from $itemList + $record : RecordFact( decomposedPoint == null ) + not RecordFact( lineNumber == $fact.lineNumber ) + then + modify($record){ + decomposedPoint = null + } + modify($item){ + decomposedPointFlag = "1" + } + modify($fact){ + itemList = $itemList + } + System.out.println("[DEBUG] after $item=" + $item); +end