/**
* Copyright 2010 JBoss Inc
*
* 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.clips;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.lang.reflect.Method;
import junit.framework.TestCase;
import org.drools.Person;
import org.drools.WorkingMemory;
import org.drools.clips.functions.AssertFunction;
import org.drools.clips.functions.BindFunction;
import org.drools.clips.functions.CallFunction;
import org.drools.clips.functions.CreateListFunction;
import org.drools.clips.functions.EqFunction;
import org.drools.clips.functions.GetFunction;
import org.drools.clips.functions.IfFunction;
import org.drools.clips.functions.LessThanFunction;
import org.drools.clips.functions.LessThanOrEqFunction;
import org.drools.clips.functions.MinusFunction;
import org.drools.clips.functions.ModifyFunction;
import org.drools.clips.functions.MoreThanFunction;
import org.drools.clips.functions.MoreThanOrEqFunction;
import org.drools.clips.functions.MultiplyFunction;
import org.drools.clips.functions.NewFunction;
import org.drools.clips.functions.PlusFunction;
import org.drools.clips.functions.PrintoutFunction;
import org.drools.clips.functions.PrognFunction;
import org.drools.clips.functions.ReturnFunction;
import org.drools.clips.functions.RunFunction;
import org.drools.clips.functions.SetFunction;
import org.drools.clips.functions.SwitchFunction;
import org.drools.common.InternalRuleBase;
import org.drools.rule.Package;
import org.drools.rule.Rule;
public class ClipsShellTest extends TestCase {
private ByteArrayOutputStream baos;
ClipsShell shell;
public void setUp() {
FunctionHandlers handlers = FunctionHandlers.getInstance();
handlers.registerFunction( new PlusFunction() );
handlers.registerFunction( new MinusFunction() );
handlers.registerFunction( new MultiplyFunction() );
handlers.registerFunction( new ModifyFunction() );
handlers.registerFunction( new CreateListFunction() );
handlers.registerFunction( new PrintoutFunction() );
handlers.registerFunction( new PrognFunction() );
handlers.registerFunction( new IfFunction() );
handlers.registerFunction( new LessThanFunction() );
handlers.registerFunction( new LessThanOrEqFunction() );
handlers.registerFunction( new MoreThanFunction() );
handlers.registerFunction( new MoreThanOrEqFunction() );
handlers.registerFunction( new EqFunction() );
handlers.registerFunction( new SwitchFunction() );
//handlers.registerFunction( new DeffunctionFunction() );
handlers.registerFunction( new ReturnFunction() );
handlers.registerFunction( new RunFunction() );
handlers.registerFunction( new BindFunction() );
handlers.registerFunction( new NewFunction() );
handlers.registerFunction( new SetFunction() );
handlers.registerFunction( new GetFunction() );
handlers.registerFunction( new CallFunction() );
handlers.registerFunction( new AssertFunction() );
this.shell = new ClipsShell();
this.baos = new ByteArrayOutputStream();
shell.addRouter( "t",
new PrintStream( baos ) );
}
// public void test1() {
// String expr = "(* (+ 4 4 ) 2) (create$ 10 20 (+ 10 10) a) (modify ?p (name mark) (location \"london\")(age (+ 16 16) ) ) (printout t a b c (+ 4 4) )";
//
// SExpression[] lisplists = evalString( expr );
//
// StringBuilderAppendable appendable = new StringBuilderAppendable();
// MVELClipsContext context = new MVELClipsContext();
// for ( SExpression sExpression : lisplists ) {
// FunctionHandlers.dump( sExpression, appendable, context );
// }
//
// System.out.println( appendable );
// }
public void testBind() {
String expr = "(bind ?x (create$ 10 20 30) ) (printout t ?x)";
this.shell.eval( expr );
assertEquals( "[10, 20, 30]",
new String( baos.toByteArray() ) );
}
public void testProgn() {
String expr = "(progn (?x (create$ 10 20 30) ) (printout t ?x) )";
this.shell.eval( expr );
assertEquals( "102030",
new String( baos.toByteArray() ) );
}
public void testIf() {
String expr = "(if (< 1 3) then (printout t hello) (printout t hello) )";
this.shell.eval( expr );
assertEquals( "hellohello",
new String( baos.toByteArray() ) );
if ( 1 <= 10 ) {
}
}
public void testIfElse() {
String expr = "(if (eq 1 3) then (printout t hello) (printout t 1) else (printout t hello) (printout t 2))";
this.shell.eval( expr );
assertEquals( "hello2",
new String( baos.toByteArray() ) );
}
public void testSwitch() throws IOException {
String expr = "(switch (?x) (case a then (printout t hello)(printout t 1)) (case b then (printout t hello)(printout t 2)) (default (printout t hello)(printout t 3)) )";
// check case a
this.shell.addVariable( "$x",
"a" );
this.shell.eval( expr );
assertEquals( "hello1",
new String( baos.toByteArray() ) );
// check default
this.shell.addVariable( "$x",
"M" );
this.shell.eval( expr );
assertEquals( "hello1hello3",
new String( baos.toByteArray() ) );
// check case b
this.shell.addVariable( "$x",
"b" );
this.shell.eval( expr );
assertEquals( "hello1hello3hello2",
new String( baos.toByteArray() ) );
}
// @FIXME - org.mvel.CompileException: unable to resolve property: unable to resolve method: org.drools.clips.Shell.max(java.lang.Integer, java.lang.Integer) [arglength=2]
public void testDeffunction() {
String function = "(deffunction max (?a ?b) (if (> ?a ?b) then (return ?a) else (return ?b) ) )";
this.shell.eval( function );
String expr = "(if (eq (max 3 5) 5) then (printout t hello) )";
this.shell.eval( expr );
assertEquals( "hello",
new String( baos.toByteArray() ) );
expr = "(if (eq (max ?a ?b) 5) then (printout t hello) )";
this.shell.addVariable( "$a",
"3" );
this.shell.addVariable( "$b",
"5" );
this.shell.eval( expr );
assertEquals( "hellohello",
new String( baos.toByteArray() ) );
}
public void testDirectImportAndNew() {
String t = "(import org.drools.Person) (bind ?p (new Person mark cheddar) ) (printout t ?p)";
this.shell.eval( t );
assertEquals( "[Person name='mark']",
new String( this.baos.toByteArray() ) );
}
public void testDynamicImportAndNew() {
String t = "(import org.drools.*) (bind ?p (new Person mark cheddar) ) (printout t ?p)";
this.shell.eval( t );
assertEquals( "[Person name='mark']",
new String( this.baos.toByteArray() ) );
}
public void testSet() {
String t = "(import org.drools.*) (bind ?p (new Person mark cheddar) ) (set ?p name bob) (printout t ?p)";
this.shell.eval( t );
assertEquals( "[Person name='bob']",
new String( this.baos.toByteArray() ) );
}
public void testGet() {
String t = "(import org.drools.*) (bind ?p (new Person mark cheddar) )(printout t (get ?p name))";
this.shell.eval( t );
assertEquals( "mark",
new String( this.baos.toByteArray() ) );
}
public void testExplicitCall() {
String t = "(import org.drools.*) (bind ?p (new Person mark cheddar) ) (call ?p setFields bob stilton 35) (printout t (call ?p toLongString))";
this.shell.eval( t );
assertEquals( "[Person name='bob' likes='stilton' age='35']",
new String( this.baos.toByteArray() ) );
}
public void testImplicitCall() {
String t = "(import org.drools.*) (bind ?p (new Person mark cheddar) ) (?p setFields bob stilton 35) (printout t (call ?p toLongString))";
this.shell.eval( t );
assertEquals( "[Person name='bob' likes='stilton' age='35']",
new String( this.baos.toByteArray() ) );
}
public void FIXME_testRuleCreation() {
this.shell.eval( "(import org.drools.Person)" );
this.shell.eval( "(defrule yyy => (printout t yy \" \" (eq 1 1) ) ) )" );
Package pkg = shell.getStatefulSession().getRuleBase().getPackage( "MAIN" );
Rule rule = pkg.getRule( "yyy" );
assertEquals( "yyy",
rule.getName() );
this.shell.eval( "(defrule xxx (Person (name ?name&bob) (age 30) ) (Person (name ?name) (age 35)) => (printout t xx \" \" (eq 1 1) ) )" );
rule = pkg.getRule( "xxx" );
assertEquals( "xxx",
rule.getName() );
assertEquals( 2,
pkg.getRules().length );
assertTrue( pkg.getImports().containsKey( "org.drools.Person" ) );
WorkingMemory wm = shell.getStatefulSession();
wm.insert( new Person( "bob",
"cheddar",
30 ) );
wm.insert( new Person( "bob",
"stilton",
35 ) );
wm.fireAllRules();
assertEquals( "yy truexx true",
new String( this.baos.toByteArray() ) );
}
public void FIXME_testTemplateCreation2() throws Exception {
this.shell.eval( "(deftemplate PersonTemplate (slot name (type String) ) (slot age (type int) ) )" );
this.shell.eval( "(defrule xxx (PersonTemplate (name ?name&bob) (age 30) ) (PersonTemplate (name ?name) (age 35)) => (printout t xx \" \" (eq 1 1) ) )" );
this.shell.eval( "(assert (PersonTemplate (name 'mike') (age 34)))" );
Class personClass = ((InternalRuleBase)this.shell.getStatefulSession().getRuleBase()).getRootClassLoader().loadClass( "MAIN.PersonTemplate" );
assertNotNull( personClass );
}
public void FIXME_testTemplateCreation() throws Exception {
this.shell.eval( "(deftemplate Person (slot name (type String) ) (slot age (type int) ) )" );
this.shell.eval( "(defrule xxx (Person (name ?name&bob) (age 30) ) => (printout t hello bob ) )" );
this.shell.eval( "(assert (Person (name bob) (age 30) ) )" );
this.shell.eval( "(run)" );
assertEquals( "hellobob",
new String( this.baos.toByteArray() ) );
}
public void FIXME_testTemplateCreationWithJava() throws Exception {
this.shell.eval( "(deftemplate Person (slot name (type String) ) (slot age (type int) ) )" );
this.shell.eval( "(defrule yyy => (printout t yy \" \" (eq 1 1) ) ) )" );
Package pkg = shell.getStatefulSession().getRuleBase().getPackage( "MAIN" );
Rule rule = pkg.getRule( "yyy" );
assertEquals( "yyy",
rule.getName() );
this.shell.eval( "(defrule xxx (Person (name ?name&bob) (age 30) ) (Person (name ?name) (age 35)) => (printout t xx \" \" (eq 1 1) ) )" );
rule = pkg.getRule( "xxx" );
assertEquals( "xxx",
rule.getName() );
assertEquals( 2,
pkg.getRules().length );
WorkingMemory wm = shell.getStatefulSession();
Class personClass = ((InternalRuleBase)this.shell.getStatefulSession().getRuleBase()).getRootClassLoader().loadClass( "MAIN.Person" );
Method nameMethod = personClass.getMethod( "setName",
new Class[]{String.class} );
Method ageMethod = personClass.getMethod( "setAge",
new Class[]{int.class} );
Object bob1 = personClass.newInstance();
nameMethod.invoke( bob1,
"bob" );
ageMethod.invoke( bob1,
30 );
Object bob2 = personClass.newInstance();
nameMethod.invoke( bob2,
"bob" );
ageMethod.invoke( bob2,
35 );
//Constructor constructor = personClass.getConstructor( new Class[] { String.class,String.class, int.class} );
wm.insert( bob1 );
wm.insert( bob2 );
wm.fireAllRules();
assertEquals( "yy truexx true",
new String( this.baos.toByteArray() ) );
}
public void FIXME_testEmptyLHSRule() {
String rule1 = "(defrule testRule => (printout t hello) (printout t goodbye))";
this.shell.eval( rule1 );
assertEquals( "hellogoodbye",
new String( this.baos.toByteArray() ) );
}
public void FIXME_testSimpleLHSRule() {
this.shell.eval( "(import org.drools.*)" );
this.shell.eval( "(defrule testRule (Person (name ?name&mark) ) => (printout t hello) (printout t \" \" ?name))" );
this.shell.eval( "(assert (Person (name mark) ) )" );
this.shell.eval( "(run)" );
assertEquals( "hello mark",
new String( this.baos.toByteArray() ) );
}
public void FIXME_testRuleCallDeftemplate() {
String function = "(deffunction max (?a ?b) (if (> ?a ?b) then (return ?a) else (return ?b) ) )";
this.shell.eval( function );
this.shell.eval( "(import org.drools.*)" );
this.shell.eval( "(defrule testRule (Person (age ?age) ) => (printout t hello) (printout t \" \" (max 3 ?age) ) )" );
this.shell.eval( "(assert (Person (name mark) (age 32) ) )" );
this.shell.eval( "(run)" );
assertEquals( "hello 32",
new String( this.baos.toByteArray() ) );
}
public void FIXME_testTwoSimpleRulesWithModify() {
this.shell.eval( "(import org.drools.*)" );
this.shell.eval( "(defrule testRule1 ?p <- (Person (name ?name&mark) ) => (printout t hello) (printout t \" \" ?name) (modify ?p (name bob) ) )" );
this.shell.eval( "(defrule testRule2 (Person (name ?name&bob) ) => (printout t hello) (printout t \" \" ?name))" );
this.shell.eval( "(assert (Person (name mark) ) )" );
this.shell.eval( "(run)" );
assertEquals( "hello markhello bob",
new String( this.baos.toByteArray() ) );
}
public void FIXME_testBlockEval() {
String text = "(import org.drools.*)";
text += "(defrule testRule1 ?p <- (Person (name ?name&mark) ) => (printout t hello) (printout t \" \" ?name) (modify ?p (name bob) ) )";
text += "(defrule testRule2 (Person (name ?name&bob) ) => (printout t hello) (printout t \" \" ?name))";
text += "(assert (Person (name mark) ) )";
text += "(run)";
this.shell.eval( text );
assertEquals( "hello markhello bob",
new String( this.baos.toByteArray() ) );
}
public void FIXME_testPredicate() {
this.shell.eval( "(import org.drools.Person)" );
this.shell.eval( "(defrule testRule1 (Person (name ?name) (age ?age&:(> ?age 30)) ) => (printout t hello) (printout t \" \" ?name) )" );
this.shell.eval( "(assert (Person (name mark) (age 27) ) )" );
this.shell.eval( "(assert (Person (name bob) (age 35) ) )" );
this.shell.eval( "(run)" );
assertEquals( "hello bob",
new String( this.baos.toByteArray() ) );
}
public void FIXME_testReturnValue() {
this.shell.eval( "(import org.drools.Person)" );
this.shell.eval( "(defrule testRule1 (Person (age ?age) ) (Person (name ?name) (age =(- ?age 3)) ) => (printout t hello) (printout t \" \" ?name) )" );
this.shell.eval( "(assert (Person (name mark) (age 32) ) )" );
this.shell.eval( "(assert (Person (name bob) (age 35) ) )" );
this.shell.eval( "(run)" );
assertEquals( "hello mark",
new String( this.baos.toByteArray() ) );
}
public void FIXME_testTest() {
this.shell.eval( "(import org.drools.Person)" );
this.shell.eval( "(defrule testRule1 (Person (age ?age1) ) (Person (name ?name) (age ?age2) ) (test(eq ?age1 (+ ?age2 3) )) => (printout t hello) )" );
this.shell.eval( "(assert (Person (name mark) (age 32) ) )" );
this.shell.eval( "(assert (Person (name bob) (age 35) ) )" );
this.shell.eval( "(run)" );
assertEquals( "hello",
new String( this.baos.toByteArray() ) );
}
public void testRun() {
this.shell.eval( "(run)" );
}
public void FIXME_testMixed() {
this.shell.eval( "(import org.drools.Cheese)" );
String str ="";
str += "(deftemplate Person ";
str += " (slot name ";
str += " (type String) ) ";
str += " (slot age";
str += " (type String) ) ";
str += " (slot location";
str += " (type String) ) ";
str += " (slot cheese";
str += " (type String) ) ";
str += ")";
this.shell.eval( str );
this.shell.eval( "(deffunction max (?a ?b) (if (> ?a ?b) then (return ?a) else (return ?b) ) )" );
str = "";
str += "(defrule sendsomecheese ";
str += " (Person (name ?name) (age ?personAge) (cheese ?cheeseType) (location \"london\") ) ";
str += " (Cheese (type ?cheeseType) (price ?cheesePrice&:(eq (max ?personAge ?cheesePrice) ?cheesePrice) ) )";
str += "\n=>\n";
str += " (printout t \"send some \" ?cheeseType \" \" to \" \" ?name) ";
str += ")";
this.shell.eval( str );
this.shell.eval( "(assert (Person (name mark) (location \"london\") (cheese \"cheddar\") (age 25) ) )" );
this.shell.eval( "(assert (Cheese (type \"cheddar\") (price 30) ) ) " );
this.shell.eval( "(run)" );
assertEquals( "send some cheddar to mark",
new String( this.baos.toByteArray() ) );
}
}