/*
* Copyright 2016 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.drools.testcoverage.regression;
import org.assertj.core.api.Assertions;
import org.drools.testcoverage.common.model.MyFact;
import org.junit.Test;
import org.kie.api.io.ResourceType;
import org.kie.api.runtime.KieSession;
import org.kie.api.runtime.rule.FactHandle;
import org.kie.internal.utils.KieHelper;
/**
* BZ 1190923 reproducer by Hisao Furuich.
*/
public class AccumulateRecalculationTest {
@Test
public void testAccumulateWithNoLoop() {
final String drl =
"import " + MyFact.class.getCanonicalName() + " ;\n" +
"rule RuleAccumulate \n" +
" no-loop true\n" +
"when\n" +
" $target: MyFact(name == \"target\")\n" +
" $sum : Integer( ) from accumulate (\n" +
" $v1: MyFact(name str[startsWith] \"src\", currentValue != null),\n" +
" init ( int total = 0; ),\n" +
" action (\n" +
" total = total + $v1.getCurrentValue().intValue();\n" +
" System.out.println(\"action : plus \" + $v1.toString() + \" then total=\" + total);\n" +
" ),\n" +
" reverse (\n" +
" total = total - \n" +
" ($v1.getPreviousValue() != null ? $v1.getPreviousValue().intValue() : $v1.getCurrentValue().intValue());\n" +
" System.out.println(\"reverse : minus \" + $v1.toString() + \" then total=\" + total);\n" +
" ),\n" +
" result ( new Integer(total) )\n" +
" );\n" +
"then\n" +
" System.out.println(\" Fired!! \" + drools.getRule().getName() + \" total=\" + $sum);\n" +
" $target.setCurrentValue($sum);\n" +
" update($target);\n" +
"end\n" +
"\n" +
"rule RuleFollowing \n" +
"when\n" +
" $target: MyFact(name == \"target\") @watch(currentValue)\n" +
"then\n" +
" System.out.println(\" Fired!! RuleFollowing target=\" + $target.toString());\n" +
"end\n";
scenario(drl);
}
@Test
public void testAccumulateWithNoLoopBySum() {
final String drl =
"import " + MyFact.class.getCanonicalName() + " ;\n" +
"rule RuleAccumulateSum \n" +
" no-loop true\n" +
"when\n" +
" $target: MyFact(name == \"target\");\n" +
" $sum : Number( ) from accumulate (\n" +
" $v1: MyFact(name str[startsWith] \"src\", $val: currentValue != null),\n" +
" sum( $val )\n" +
" );\n" +
"then\n" +
" System.out.println(\" Fired!! \" + drools.getRule().getName() + \" total=\" + $sum);\n" +
" $target.setCurrentValue($sum.intValue());\n" +
" update($target);\n" +
"end\n" +
"\n" +
"rule RuleFollowing \n" +
"when\n" +
" $target: MyFact(name == \"target\") @watch(currentValue)\n" +
"then\n" +
" System.out.println(\" Fired!! RuleFollowing target=\" + $target.toString());\n" +
"end\n";
scenario(drl);
}
@Test
public void testCollect() {
final String drl =
"import java.util.ArrayList;\n" +
" import " + MyFact.class.getCanonicalName() + " ;\n" +
"rule RuleCollect \n" +
" no-loop true\n" +
"when\n" +
" $target: MyFact(name == \"target\");\n" +
" $list : ArrayList( size > 0 ) from collect (\n" +
" $v1: MyFact(name str[startsWith] \"src\", $val: currentValue != null)\n" +
" );\n" +
"then\n" +
" int $sum = 0;\n" +
" for (Object obj : $list) {\n" +
" MyFact myFact = (MyFact)obj;\n" +
" $sum = $sum + ((MyFact)obj).getCurrentValue().intValue();\n" +
" System.out.println(\" sum + \" + myFact.toString() + \" total is \" + $sum);\n" +
" }\n" +
" System.out.println(\" Fired!! \" + drools.getRule().getName() + \" total=\" + $sum);\n" +
" $target.setCurrentValue($sum);\n" +
" update($target);\n" +
"end\n" +
"\n" +
"rule RuleFollowing \n" +
"when\n" +
" $target: MyFact(name == \"target\") @watch(currentValue)\n" +
"then\n" +
" System.out.println(\" Fired!! RuleFollowing target=\" + $target.toString());\n" +
"end\n";
scenario(drl);
}
@Test
public void testWithOutAccumulateCollect() {
final String drl =
"import " + MyFact.class.getCanonicalName() + " ;\n" +
"rule RuleWithOutAccumulateCollect \n" +
" no-loop true\n" +
"when\n" +
" $target: MyFact(name == \"target\");\n" +
" $src1 : MyFact(name str[startsWith] \"src\", currentValue != null);\n" +
" $src2 : MyFact(hashCode() < $src1.hashCode(), name str[startsWith] \"src\", currentValue != null);\n" +
"then\n" +
" int $sum = $src1.getCurrentValue().intValue();\n" +
" $sum += $src2.getCurrentValue().intValue();\n" +
" System.out.println(\" Fired!! \" + drools.getRule().getName() + \" total=\" + $sum);\n" +
" $target.setCurrentValue($sum);\n" +
" update($target);\n" +
"end\n" +
"\n" +
"rule RuleFollowing \n" +
"when\n" +
" $target: MyFact(name == \"target\") @watch(currentValue)\n" +
"then\n" +
" System.out.println(\" Fired!! RuleFollowing target=\" + $target.toString());\n" +
"end\n";
scenario(drl);
}
private void scenario(final String drl) {
final KieSession ksession = new KieHelper().addContent(drl, ResourceType.DRL).build().newKieSession();
final MyFact fact0 = new MyFact("target", 0);
final MyFact fact1 = new MyFact("src1", 4);
final MyFact fact2 = new MyFact("src2", 5);
final FactHandle fh0 = ksession.insert(fact0);
final FactHandle fh1 = ksession.insert(fact1);
final FactHandle fh2 = ksession.insert(fact2);
int fireCount = ksession.fireAllRules();
Assertions.assertThat(fact0.getCurrentValue().intValue()).isEqualTo(9);
Assertions.assertThat(fireCount).isEqualTo(2);
fact2.setCurrentValue(6);
ksession.update(fh2, fact2);
fireCount = ksession.fireAllRules();
Assertions.assertThat(fact0.getCurrentValue().intValue()).isEqualTo(10);
Assertions.assertThat(fireCount).isEqualTo(2);
}
}