Package org.drools.agent

Source Code of org.drools.agent.KnowledgeAgentIncrementalChangeSetTest

package org.drools.agent;

import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;


import org.drools.KnowledgeBase;
import org.drools.KnowledgeBaseFactory;
import org.drools.runtime.rule.QueryResults;
import org.drools.builder.KnowledgeBuilder;
import org.drools.builder.KnowledgeBuilderFactory;
import org.drools.builder.ResourceType;
import org.drools.definition.KnowledgePackage;
import org.drools.definition.rule.Rule;
import org.drools.definitions.impl.KnowledgePackageImp;
import org.drools.io.ResourceFactory;
import org.drools.runtime.StatefulKnowledgeSession;
import org.drools.runtime.rule.FactHandle;
import org.drools.runtime.rule.QueryResultsRow;

import org.junit.Ignore;
import org.junit.Test;

import static org.junit.Assert.*;

public class KnowledgeAgentIncrementalChangeSetTest extends BaseKnowledgeAgentTest {

    @Test
    public void testModifyFileUrlIncremental() throws Exception {
        fileManager.write( "rule1.drl",
                           createDefaultRule( "rule1" ) );

        fileManager.write( "rule2.drl",
                           createDefaultRule( "rule2" ) );

        String xml = "";
        xml += "<change-set xmlns='http://drools.org/drools-5.0/change-set'";
        xml += "    xmlns:xs='http://www.w3.org/2001/XMLSchema-instance'";
        xml += "    xs:schemaLocation='http://drools.org/drools-5.0/change-set http://anonsvn.jboss.org/repos/labs/labs/jbossrules/trunk/drools-api/src/main/resources/change-set-1.0.0.xsd' >";
        xml += "    <add> ";
        xml += "        <resource source='http://localhost:" + this.getPort() + "/rule1.drl' type='DRL' />";
        xml += "        <resource source='http://localhost:" + this.getPort() + "/rule2.drl' type='DRL' />";
        xml += "    </add> ";
        xml += "</change-set>";
        File fxml = fileManager.write( "changeset.xml",
                                       xml );

        KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
        KnowledgeAgent kagent = this.createKAgent( kbase,
                                                   false );

        kagent.applyChangeSet( ResourceFactory.newUrlResource( fxml.toURI().toURL() ) );

        StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
        List<String> list = new ArrayList<String>();
        ksession.setGlobal( "list",
                            list );
        ksession.fireAllRules();

        assertEquals( 2,
                      list.size() );
        assertTrue( list.contains( "rule1" ) );
        assertTrue( list.contains( "rule2" ) );

        list.clear();

        fileManager.write( "rule1.drl",
                           createDefaultRule( "rule3" ) );

        scan( kagent );

        // Use the same session for incremental build test
        ksession.fireAllRules();
        ksession.dispose();

        assertEquals( 1,
                      list.size() );

        assertTrue( list.contains( "rule3" ) );
        ksession.dispose();

        // Check rule2 is still there
        ksession = kbase.newStatefulKnowledgeSession();
        list = new ArrayList<String>();
        ksession.setGlobal( "list",
                            list );
        ksession.fireAllRules();

        assertEquals( 2,
                      list.size() );
        assertTrue( list.contains( "rule3" ) );
        assertTrue( list.contains( "rule2" ) );

        ksession.dispose();
        kagent.dispose();
    }

    @Test
    public void testRemoveFileUrlIncremental() throws Exception {
        File f1 = fileManager.write( "rule1.drl",
                                     createLhsRule( "rule1",
                                                    "String()" ) );

        File f2 = fileManager.write( "rule2.drl",
                                     createLhsRule( "rule2",
                                                    "String()" ) );

        String xml = "";
        xml += "<change-set xmlns='http://drools.org/drools-5.0/change-set'";
        xml += "    xmlns:xs='http://www.w3.org/2001/XMLSchema-instance'";
        xml += "    xs:schemaLocation='http://drools.org/drools-5.0/change-set http://anonsvn.jboss.org/repos/labs/labs/jbossrules/trunk/drools-api/src/main/resources/change-set-1.0.0.xsd' >";
        xml += "    <add> ";
        xml += "        <resource source='http://localhost:" + this.getPort() + "/rule1.drl' type='DRL' />";
        xml += "        <resource source='http://localhost:" + this.getPort() + "/rule2.drl' type='DRL' />";
        xml += "    </add> ";
        xml += "</change-set>";
        File fxml = fileManager.write( "changeset.xml",
                                       xml );

        KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();

        KnowledgeAgent kagent = this.createKAgent( kbase,
                                                   false );

        kagent.applyChangeSet( ResourceFactory.newUrlResource( fxml.toURI().toURL() ) );

        StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
        List<String> list = new ArrayList<String>();
        ksession.setGlobal( "list",
                            list );
        ksession.insert( "String1" );
        ksession.fireAllRules();

        assertEquals( 2,
                      list.size() );
        assertTrue( list.contains( "rule1" ) );
        assertTrue( list.contains( "rule2" ) );

        list.clear();

        // Delete the file so only rule 2 fires
        this.fileManager.deleteFile( f1 );
        scan( kagent );

        ksession.insert( "String2" );
        ksession.fireAllRules();

        assertEquals( 1,
                      list.size() );
        assertTrue( list.contains( "rule2" ) );

        //Delete f2 now, no rules should fire
        list.clear();

        this.fileManager.deleteFile( f2 );
        scan( kagent );

        ksession.insert( "String3" );
        ksession.fireAllRules();

        assertEquals( 0,
                      list.size() );

        ksession.dispose();

        kagent.dispose();
    }

    /**
     * Tests that if we have two DRL files, where one file overwrites a rule in
     * a prior file, that if we modify the first file that was overwritten, that
     * it will gain precedence and overwrite the other.
     *
     * @throws Exception
     */
    @Test
    public void testModifyFileUrlOverwriteIncremental() throws Exception {
        File f1 = fileManager.write( "rule1.drl",
                                     createLhsRule( new String[]{"rule1", "rule2"},
                                                    "String()\n" ) );

        File f2 = fileManager.write( "rule2.drl",
                                     createVersionedRule( null,
                                                          new String[]{"rule1"},
                                                          null,
                                                          "String()\n",
                                                          "2" ) );

        String xml = "";
        xml += "<change-set xmlns='http://drools.org/drools-5.0/change-set'";
        xml += "    xmlns:xs='http://www.w3.org/2001/XMLSchema-instance'";
        xml += "    xs:schemaLocation='http://drools.org/drools-5.0/change-set http://anonsvn.jboss.org/repos/labs/labs/jbossrules/trunk/drools-api/src/main/resources/change-set-1.0.0.xsd' >";
        xml += "    <add> ";
        xml += "        <resource source='http://localhost:" + this.getPort() + "/rule1.drl' type='DRL' />";
        xml += "        <resource source='http://localhost:" + this.getPort() + "/rule2.drl' type='DRL' />";
        xml += "    </add> ";
        xml += "</change-set>";
        File fxml = fileManager.write( "changeset.xml",
                                       xml );

        KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();

        KnowledgeAgent kagent = this.createKAgent( kbase,
                                                   false );

        kagent.applyChangeSet( ResourceFactory.newUrlResource( fxml.toURI().toURL() ) );

        StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
        List<String> list = new ArrayList<String>();
        ksession.setGlobal( "list",
                            list );
        ksession.insert( "String1" );
        ksession.fireAllRules();

        assertEquals( 2,
                      list.size() );
        assertTrue( list.contains( "rule1-V2" ) );
        assertTrue( list.contains( "rule2" ) );

        list.clear();

        File f3 = fileManager.write( "rule2.drl",
                                     createVersionedRule( "rule1",
                                                          "3" ) );

        scan( kagent );

        ksession.insert( "String2" );

        ksession.fireAllRules();

        assertEquals( 2,
                      list.size() );
        assertTrue( list.contains( "rule1-V3" ) );
        assertTrue( list.contains( "rule2" ) );

        //Delete f2 now, rule1 should still fire if the indexing worked properly
        list.clear();
        this.fileManager.deleteFile( f2 );

        scan( kagent );

        ksession.insert( "String3" );
        ksession.fireAllRules();

        assertEquals( 1,
                      list.size() );
        assertTrue( list.contains( "rule2" ) );

        ksession.dispose();
        kagent.dispose();
    }

    /**
     * Creates two rules (rule1 and rule2) in a drl file. Then it modifies the
     * drl file to change rule2 with rule3.
     * @throws Exception
     */
    @Test
    public void testMultipleRulesOnFileUrlIncremental() throws Exception {

        File f1 = fileManager.write( "rules.drl",
                                     createLhsRule( new String[]{"rule1", "rule2"},
                                                    "String()\n" ) );

        String xml = "";
        xml += "<change-set xmlns='http://drools.org/drools-5.0/change-set'";
        xml += "    xmlns:xs='http://www.w3.org/2001/XMLSchema-instance'";
        xml += "    xs:schemaLocation='http://drools.org/drools-5.0/change-set http://anonsvn.jboss.org/repos/labs/labs/jbossrules/trunk/drools-api/src/main/resources/change-set-1.0.0.xsd' >";
        xml += "    <add> ";
        xml += "        <resource source='http://localhost:" + this.getPort() + "/rules.drl' type='DRL' />";
        xml += "    </add> ";
        xml += "</change-set>";
        File fxml = fileManager.write( "changeset.xml",
                                       xml );

        KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();

        KnowledgeAgent kagent = this.createKAgent( kbase,
                                                   false );

        kagent.applyChangeSet( ResourceFactory.newUrlResource( fxml.toURI().toURL() ) );

        StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
        List<String> list = new ArrayList<String>();
        ksession.setGlobal( "list",
                            list );
        ksession.insert( "String1" );
        ksession.fireAllRules();
        ksession.dispose();

        assertEquals( 2,
                      list.size() );
        assertTrue( list.contains( "rule1" ) );
        assertTrue( list.contains( "rule2" ) );

        list.clear();

        fileManager.write( "rules.drl",
                            createLhsRule( new String[]{"rule1", "rule3"},
                                           "String()\n" ) );

        scan( kagent );

        // Use the same session for incremental build test
        ksession.insert( "String2" );
        ksession.fireAllRules();

        assertEquals( 2,
                      list.size() );
        assertTrue( list.contains( "rule1" ) );
        assertTrue( list.contains( "rule3" ) );

        ksession.dispose();
        kagent.dispose();
    }

    @Test
    public void testMultipleRulesOnFilesUrlIncremental() throws Exception {

        File f1 = fileManager.write( "rules1.drl",
                                     createLhsRule( new String[]{"rule1", "rule2"},
                                                    "String()\n" ) );

        fileManager.write( "rules2.drl",
                           createLhsRule( "rule3",
                                          "String()\n" ) );

        String xml = "";
        xml += "<change-set xmlns='http://drools.org/drools-5.0/change-set'";
        xml += "    xmlns:xs='http://www.w3.org/2001/XMLSchema-instance'";
        xml += "    xs:schemaLocation='http://drools.org/drools-5.0/change-set http://anonsvn.jboss.org/repos/labs/labs/jbossrules/trunk/drools-api/src/main/resources/change-set-1.0.0.xsd' >";
        xml += "    <add> ";
        xml += "        <resource source='http://localhost:" + this.getPort() + "/rules1.drl' type='DRL' />";
        xml += "        <resource source='http://localhost:" + this.getPort() + "/rules2.drl' type='DRL' />";
        xml += "    </add> ";
        xml += "</change-set>";
        File fxml = fileManager.write( "changeset.xml",
                                       xml );

        KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();

        KnowledgeAgent kagent = createKAgent( kbase,
                                              false );

        applyChangeSet( kagent,
                        ResourceFactory.newUrlResource( fxml.toURI().toURL() ) );

        StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
        List<String> list = new ArrayList<String>();
        ksession.setGlobal( "list",
                            list );
        FactHandle h1 = ksession.insert( "String1" );
        ksession.fireAllRules();

        assertEquals( 3,
                      list.size() );
        assertTrue( list.contains( "rule1" ) );
        assertTrue( list.contains( "rule2" ) );
        assertTrue( list.contains( "rule3" ) );

        list.clear();
        fileManager.write( "rules2.drl",
                           createLhsRule( "rule4",
                                          "String()\n" ) );
        scan( kagent );

        // Use the same session for incremental build test
        // Fact is still there, so should match against latest new rule
        ksession.fireAllRules();
        assertEquals( 1,
                      list.size() );
        assertTrue( list.contains( "rule4" ) );

        list.clear();
        ksession.retract( h1 );

        ksession.insert( "String2" );
        ksession.fireAllRules();
        assertEquals( 3,
                      list.size() );
        assertTrue( list.contains( "rule1" ) );
        assertTrue( list.contains( "rule2" ) );
        assertTrue( list.contains( "rule4" ) );

        list.clear();
        fileManager.write( "rules1.drl",
                           createLhsRule( new String[]{"rule1", "rule5"},
                                          "String()\n" ) );
        scan( kagent );

        // Fact is still there, so should match against latest new rule       
        ksession.fireAllRules();
        assertEquals( 1,
                      list.size() );
        assertTrue( list.contains( "rule5" ) );

        ksession.retract( h1 );
        list.clear();

        ksession.insert( "String3" );
        ksession.fireAllRules();
        assertEquals( 3,
                      list.size() );
        assertTrue( list.contains( "rule1" ) );
        assertTrue( list.contains( "rule5" ) );
        assertTrue( list.contains( "rule4" ) );

        ksession.dispose();
        kagent.dispose();
    }

    @Test
    public void testModifyPackageUrlIncremental() throws Exception {

        // Put just Rule1 in the first package
        File pkg1 = fileManager.newFile( "pkg1.pkg" );
        KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
        kbuilder.add( ResourceFactory.newByteArrayResource( createLhsRule( "rule1",
                                                                           "String()\n" ).getBytes() ),
                      ResourceType.DRL );
        if ( kbuilder.hasErrors() ) {
            fail( kbuilder.getErrors().toString() );
        }
        KnowledgePackage pkg = (KnowledgePackage) kbuilder.getKnowledgePackages().iterator().next();
        writePackage( pkg,
                      pkg1 );

        String xml = "";
        xml += "<change-set xmlns='http://drools.org/drools-5.0/change-set'";
        xml += "    xmlns:xs='http://www.w3.org/2001/XMLSchema-instance'";
        xml += "    xs:schemaLocation='http://drools.org/drools-5.0/change-set http://anonsvn.jboss.org/repos/labs/labs/jbossrules/trunk/drools-api/src/main/resources/change-set-1.0.0.xsd' >";
        xml += "    <add> ";
        xml += "        <resource source='http://localhost:" + this.getPort() + "/pkg1.pkg' type='PKG' />";
        xml += "    </add> ";
        xml += "</change-set>";
        File fxml = fileManager.write( "changeset.xml",
                                       xml );

        KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
        KnowledgeAgent kagent = createKAgent( kbase,
                                              false );
        applyChangeSet( kagent,
                        ResourceFactory.newUrlResource( fxml.toURI().toURL() ) );

        StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
        List<String> list = new ArrayList<String>();
        ksession.setGlobal( "list",
                            list );
        ksession.insert( "String1" );
        ksession.fireAllRules();

        assertEquals( 1,
                      list.size() );
        assertTrue( list.contains( "rule1" ) );

        list.clear();

        kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
        kbuilder.add( ResourceFactory.newByteArrayResource( createLhsRule( "rule3",
                                                                           "String()\n" ).getBytes() ),
                      ResourceType.DRL );
        kbuilder.add( ResourceFactory.newByteArrayResource( createLhsRule( "rule2",
                                                                           "String()\n" ).getBytes() ),
                      ResourceType.DRL );
        if ( kbuilder.hasErrors() ) {
            fail( kbuilder.getErrors().toString() );
        }
        pkg = (KnowledgePackage) kbuilder.getKnowledgePackages().iterator().next();
        writePackage( pkg,
                      pkg1 );

        scan( kagent );
        ksession.fireAllRules();

        assertEquals( 2,
                      list.size() );
        assertTrue( list.contains( "rule3" ) );
        assertTrue( list.contains( "rule2" ) );

        list.clear();
        ksession.insert( "String2" );
        ksession.fireAllRules();
        assertEquals( 2,
                      list.size() );
        assertTrue( list.contains( "rule3" ) );
        assertTrue( list.contains( "rule2" ) );

        ksession.dispose();
        kagent.dispose();
    }

    @Test @Ignore
    public void testUpdatePackageUrlIncremental() throws Exception {

        // Add Rule1 and Rule2 in the first package
        File pkg1 = fileManager.newFile( "pkg1.pkg" );
        KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
        kbuilder.add( ResourceFactory.newByteArrayResource( createLhsRule( "rule1",
                                                                           "String()\n" ).getBytes() ),
                      ResourceType.DRL );
        kbuilder.add( ResourceFactory.newByteArrayResource( createLhsRule( "rule2",
                                                                           "String()\n" ).getBytes() ),
                      ResourceType.DRL );
        if ( kbuilder.hasErrors() ) {
            fail( kbuilder.getErrors().toString() );
        }
        KnowledgePackage pkg = (KnowledgePackage) kbuilder.getKnowledgePackages().iterator().next();
        writePackage( pkg,
                      pkg1 );

        String xml = "";
        xml += "<change-set xmlns='http://drools.org/drools-5.0/change-set'";
        xml += "    xmlns:xs='http://www.w3.org/2001/XMLSchema-instance'";
        xml += "    xs:schemaLocation='http://drools.org/drools-5.0/change-set http://anonsvn.jboss.org/repos/labs/labs/jbossrules/trunk/drools-api/src/main/resources/change-set-1.0.0.xsd' >";
        xml += "    <add> ";
        xml += "        <resource source='http://localhost:" + this.getPort() + "/pkg1.pkg' type='PKG' />";
        xml += "    </add> ";
        xml += "</change-set>";
        File fxml = fileManager.write( "changeset.xml",
                                       xml );

        KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();

        KnowledgeAgent kagent = this.createKAgent( kbase,
                                                   false );

        kagent.applyChangeSet( ResourceFactory.newUrlResource( fxml.toURI().toURL() ) );

        StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
        List<String> list = new ArrayList<String>();
        ksession.setGlobal( "list",
                            list );
        ksession.insert( "String1" );
        ksession.fireAllRules();

        assertEquals( 2,
                      list.size() );
        assertTrue( list.contains( "rule1" ) );
        assertTrue( list.contains( "rule2" ) );

        list.clear();

        kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
        kbuilder.add( ResourceFactory.newByteArrayResource( createDefaultRule( "rule2" ).getBytes() ),
                      ResourceType.DRL );
        kbuilder.add( ResourceFactory.newByteArrayResource( createDefaultRule( "rule3" ).getBytes() ),
                      ResourceType.DRL );
        if ( kbuilder.hasErrors() ) {
            fail( kbuilder.getErrors().toString() );
        }
        pkg = (KnowledgePackage) kbuilder.getKnowledgePackages().iterator().next();
        writePackage( pkg,
                      pkg1 );

        scan( kagent );
        ksession.fireAllRules();

        // !!! MDP rule2 is not new, it should not have fired
        assertEquals( 1,
                      list.size() );
        assertTrue( list.contains( "rule3" ) );

        list.clear();
        ksession.insert( "String2" );
        ksession.fireAllRules();
        assertEquals( 2,
                      list.size() );
        assertTrue( list.contains( "rule2" ) );
        assertTrue( list.contains( "rule3" ) );
        ksession.dispose();
        kagent.dispose();
    }

    @Test
    public void testUpdatePackageUrlOverwriteIncremental() throws Exception {

        // Add Rule1 and Rule2 in the first package
        File pkgF1 = fileManager.newFile( "pkg1.pkg" );
        KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
        kbuilder.add( ResourceFactory.newByteArrayResource( createLhsRule( "rule1",
                                                                           "String()\n" ).getBytes() ),
                      ResourceType.DRL );
        kbuilder.add( ResourceFactory.newByteArrayResource( createLhsRule( "rule2",
                                                                           "String()\n" ).getBytes() ),
                      ResourceType.DRL );
        if ( kbuilder.hasErrors() ) {
            fail( kbuilder.getErrors().toString() );
        }
        KnowledgePackage pkg1 = (KnowledgePackage) kbuilder.getKnowledgePackages().iterator().next();
        writePackage( pkg1,
                      pkgF1 );

        // Add Rule3 in the second package
        File pkgF2 = fileManager.newFile( "pkg2.pkg" );
        kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
        kbuilder.add( ResourceFactory.newByteArrayResource( createDefaultRule( "rule3" ).getBytes() ),
                      ResourceType.DRL );
        if ( kbuilder.hasErrors() ) {
            fail( kbuilder.getErrors().toString() );
        }
        KnowledgePackage pkg2 = (KnowledgePackage) kbuilder.getKnowledgePackages().iterator().next();
        writePackage( pkg2,
                      pkgF2 );

        String xml = "";
        xml += "<change-set xmlns='http://drools.org/drools-5.0/change-set'";
        xml += "    xmlns:xs='http://www.w3.org/2001/XMLSchema-instance'";
        xml += "    xs:schemaLocation='http://drools.org/drools-5.0/change-set http://anonsvn.jboss.org/repos/labs/labs/jbossrules/trunk/drools-api/src/main/resources/change-set-1.0.0.xsd' >";
        xml += "    <add> ";
        xml += "        <resource source='http://localhost:" + this.getPort() + "/pkg1.pkg' type='PKG' />";
        xml += "        <resource source='http://localhost:" + this.getPort() + "/pkg2.pkg' type='PKG' />";
        xml += "    </add> ";
        xml += "</change-set>";
        File fxml = fileManager.write( "changeset.xml",
                                       xml );

        KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
        KnowledgeAgent kagent = this.createKAgent( kbase,
                                                   false );

        StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();

        applyChangeSet( kagent,
                        ResourceFactory.newUrlResource( fxml.toURI().toURL() ) );

        List<String> list = new ArrayList<String>();
        ksession.setGlobal( "list",
                            list );
        FactHandle h1 = ksession.insert( "String1" );
        ksession.fireAllRules();

        assertEquals( 3,
                      list.size() );
        assertTrue( list.contains( "rule1" ) );
        assertTrue( list.contains( "rule2" ) );
        assertTrue( list.contains( "rule3" ) );

        list.clear();

        kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
        kbuilder.add( ResourceFactory.newByteArrayResource( createVersionedRule( null,
                                                                                 new String[]{"rule1"},
                                                                                 null,
                                                                                 "String()",
                                                                                 "2" ).getBytes() ),
                      ResourceType.DRL );
        if ( kbuilder.hasErrors() ) {
            fail( kbuilder.getErrors().toString() );
        }
        pkg2 = (KnowledgePackage) kbuilder.getKnowledgePackages().iterator().next();
        writePackage( pkg2,
                      pkgF2 );

        scan( kagent );

        ksession.fireAllRules();

        assertEquals( 1,
                      list.size() );
        assertTrue( list.contains( "rule1-V2" ) );
        list.clear();

        ksession.retract( h1 );
        ksession.insert( "String2" );

        ksession.fireAllRules();

        assertEquals( 2,
                      list.size() );

        assertTrue( list.contains( "rule1-V2" ) );
        assertTrue( list.contains( "rule2" ) );

        ksession.dispose();
        kagent.dispose();
    }

    @Test @Ignore
    public void testCompleteRuleScenario() throws Exception {
        File f1 = fileManager.write( "rule1.drl",
                                     createLhsRule( new String[]{"rule1", "rule2"},
                                                    "String()\n" ) );

        File f2 = fileManager.write( "rule2.drl",
                                     createLhsRule( "rule3",
                                                    "String()\n" ) );

        String xml = "";
        xml += "<change-set xmlns='http://drools.org/drools-5.0/change-set'";
        xml += "    xmlns:xs='http://www.w3.org/2001/XMLSchema-instance'";
        xml += "    xs:schemaLocation='http://drools.org/drools-5.0/change-set http://anonsvn.jboss.org/repos/labs/labs/jbossrules/trunk/drools-api/src/main/resources/change-set-1.0.0.xsd' >";
        xml += "    <add> ";
        xml += "        <resource source='http://localhost:" + this.getPort() + "/rule1.drl' type='DRL' />";
        xml += "        <resource source='http://localhost:" + this.getPort() + "/rule2.drl' type='DRL' />";
        xml += "    </add> ";
        xml += "</change-set>";
        File fxml = fileManager.write( "changeset.xml",
                                           xml );

        KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
        KnowledgeAgent kagent = this.createKAgent( kbase,
                                                   false );
        StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
        FactHandle h1 = ksession.insert( "String1" );

        applyChangeSet( kagent,
                        ResourceFactory.newUrlResource( fxml.toURI().toURL() ) );

        List<String> list = new ArrayList<String>();
        ksession.setGlobal( "list",
                            list );
        ksession.fireAllRules();

        assertEquals( 3,
                      list.size() );
        assertTrue( list.contains( "rule1" ) );
        assertTrue( list.contains( "rule2" ) );
        assertTrue( list.contains( "rule3" ) );

        list.clear();

        File f3 = fileManager.write( "rule3.drl",
                                     createVersionedRule( null,
                                                          new String[]{"rule1"},
                                                          null,
                                                          "String()\n",
                                                          "2" ) );
        xml = "";
        xml += "<change-set xmlns='http://drools.org/drools-5.0/change-set'";
        xml += "    xmlns:xs='http://www.w3.org/2001/XMLSchema-instance'";
        xml += "    xs:schemaLocation='http://drools.org/drools-5.0/change-set http://anonsvn.jboss.org/repos/labs/labs/jbossrules/trunk/drools-api/src/main/resources/change-set-1.0.0.xsd' >";
        xml += "    <add> ";
        xml += "        <resource source='http://localhost:" + this.getPort() + "/rule3.drl' type='DRL' />";
        xml += "    </add> ";
        xml += "</change-set>";
        fxml = fileManager.write( "changeset.xml",
                                      xml );

        applyChangeSet( kagent,
                        ResourceFactory.newUrlResource( fxml.toURI().toURL() ) );

        // Check as a result of old data against new rules
        ksession.fireAllRules();
        assertEquals( 1,
                      list.size() );
       
        assertTrue( list.contains( "rule1-V2" ) );
        list.clear();

        // Check all rules are still there with new data
        ksession.retract( h1 );
        h1 = ksession.insert( "String2" );
        ksession.fireAllRules();
        assertEquals( 3,
                      list.size() );
        assertTrue( list.contains( "rule1-V2" ) );
        assertTrue( list.contains( "rule2" ) );
        assertTrue( list.contains( "rule3" ) );
        list.clear();

        f2 = fileManager.write( "rule2.drl",
                                createLhsRule( new String[]{"rule3",
                                                            "rule4"},
                                               "String()\n" ) );
        scan( kagent );

        // Check as a result of old data against new rules
        ksession.fireAllRules();
        assertEquals( 1,
                      list.size() );
        assertTrue( list.contains( "rule4" ) );
        list.clear();

        // Check all rules are still there with new data
        ksession.retract( h1 );
        h1 = ksession.insert( "String3" );
        ksession.fireAllRules();
        assertEquals( 4,
                      list.size() );
        assertTrue( list.contains( "rule1-V2" ) );
        assertTrue( list.contains( "rule2" ) );
        assertTrue( list.contains( "rule3" ) );
        assertTrue( list.contains( "rule4" ) );
        list.clear();

        f3 = fileManager.write( "rule3.drl",
                                createVersionedRule( null,
                                                     new String[]{"rule3"},
                                                     null,
                                                     "String()",
                                                     "2" ) );

        scan( kagent );

        // Check as a result of old data against new rules
        ksession.fireAllRules();
        assertEquals( 1,
                      list.size() );
        assertTrue( list.contains( "rule3-V2" ) );
        list.clear();

        // !!! MDP this logic is wrong rule3 and rule3-v2 should both exist
        //     rule3 is in rule2.drl and rule3-V2 is in rules3.drl

        // Check all rules are still there with new data
        ksession.retract( h1 );
        h1 = ksession.insert( "String4" );
        ksession.fireAllRules();
        assertEquals( 3,
                      list.size() );
        assertTrue( list.contains( "rule2" ) );
        assertTrue( list.contains( "rule3-V2" ) );
        assertTrue( list.contains( "rule4" ) );
        list.clear();

        this.fileManager.deleteFile( f3 );
        scan( kagent );

        // Check remaining rules are still there with new data
        ksession.retract( h1 );
        h1 = ksession.insert( "String5" );
        ksession.fireAllRules();
        assertEquals( 2,
                      list.size() );
        assertTrue( list.contains( "rule2" ) );
        assertTrue( list.contains( "rule4" ) );
        list.clear();

        String str = createHeader( "org.drools.test" ) +
                     createVersionedRule( false,
                                          null,
                                          new String[]{"rule1"},
                                          null,
                                          "String()\n",
                                          "3" ) +
                     createVersionedRule( false,
                                          null,
                                          new String[]{"rule3", "rule4"},
                                          null,
                                          "String()\n",
                                          null );

        System.out.println( str );

        f2 = fileManager.write( "rule2.drl",
                                str );
        scan( kagent );

        ksession.fireAllRules();

        System.out.println( list );

        // MDP the logic from this point is wrong. Rule3 was removed when added, so it should be in the list

        //        File f3 = fileManager.write( "rule3.drl",
        //                                     createVersionedRule( null,
        //                                                          new String[]{"rule1"},
        //                                                          null,
        //                                                          "String()\n",
        //                                                          "2" ) );
        //   
        //            //adds rules1-V3 definition to rules2.drl
        //            output = new BufferedWriter(new FileWriter(f2));
        //            output.write(header);
        //            output.write(rule1V3);
        //            output.write(rule3);
        //            output.write(rule4);
        //            output.close();
        //            System.gc();
        //            Thread.sleep(3000);
        //   
        //            ksession = kbase.newStatefulKnowledgeSession();
        //            list = new ArrayList<String>();
        //            ksession.setGlobal("list", list);
        //            ksession.fireAllRules();
        //            ksession.dispose();
        //   
        assertEquals( 2,
                      list.size() );
        assertTrue( list.contains( "rule1-V3" ) );
        assertTrue( list.contains( "rule3" ) );
        list.clear();
       
        ksession.retract( h1 );
        h1 = ksession.insert( "String5" );
        ksession.fireAllRules();
       
        //rule3 doesn't reapear because it was not modified in the resource
        //assertTrue(list.contains("rule3"));
       
       
        assertEquals( 4,
                      list.size() );
        assertTrue( list.contains( "rule1-V3" ) );
        assertTrue( list.contains( "rule2" ) );
        assertTrue( list.contains( "rule3" ) );
        assertTrue( list.contains( "rule4" ) );
        //   
        //            kagent.monitorResourceChangeEvents(false);
        ksession.dispose();
        kagent.dispose();

    }

    @Test
    public void testAddModifyFunctionIncremental() throws Exception {
        File f1 = fileManager.write( "rule1.drl",
                                     createCustomRule( true, null, new String[] { "rule1" },
                                                       null, "String()\n", "function1 (list,drools.getRule().getName());\n") );
       
        String xml = "";
        xml += "<change-set xmlns='http://drools.org/drools-5.0/change-set'";
        xml += "    xmlns:xs='http://www.w3.org/2001/XMLSchema-instance'";
        xml += "    xs:schemaLocation='http://drools.org/drools-5.0/change-set http://anonsvn.jboss.org/repos/labs/labs/jbossrules/trunk/drools-api/src/main/resources/change-set-1.0.0.xsd' >";
        xml += "    <add> ";
        xml += "        <resource source='http://localhost:" + this.getPort() + "/rule1.drl' type='DRL' />";
        xml += "    </add> ";
        xml += "</change-set>";
        File fxml = fileManager.write( "changeset.xml",
                                       xml );

        KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
        KnowledgeAgent kagent = this.createKAgent( kbase, false );

        try {
            applyChangeSet( kagent,
                            ResourceFactory.newUrlResource( fxml.toURI().toURL() ) );
            fail( "Knowledge should fail to compile" );
        } catch (Exception e) {
           
        }
        KnowledgePackage knowledgePackage = kbase.getKnowledgePackage( "org.drools.test" );

        //the resource didn't compile because function1 doesn't exist
        assertNull( knowledgePackage );

        //we are going to add function1 now
        String function1 = this.createCommonFunction( "function1",
                                                      "function1" );
        fileManager.write( "rule1.drl",
                           function1 +
                           createCustomRule( false, null, new String[] { "rule1" },
                                             null, "String()\n", "function1 (list, drools.getRule().getName());\n") );
        scan( kagent );

        StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
        List<String> list = new ArrayList<String>();
        ksession.setGlobal( "list",
                            list );
        ksession.insert( "String1" );
        ksession.fireAllRules();

        assertEquals( 1,
                      list.size() );
        assertTrue( list.contains( "function1 from rule1" ) );
        list.clear();

        String function2 = this.createCommonFunction( "function1",
                                                      "function1-V2" );
        fileManager.write( "rule1.drl",
                           function2 +
                           createCustomRule( false, null, new String[] { "rule1" },
                                             null, "String()\n", "function1 (list, drools.getRule().getName());\n") );
       
        //we are going to modify the definition of function1()
        //we are going to modify function1 now
        scan( kagent );

        ksession.fireAllRules();

        // Rule 1 already existed as is, so should not cause data propagation
        assertEquals( 0,
                      list.size() );
       
        ksession.insert( "String2" );
        ksession.fireAllRules();
       
        assertEquals( 1,
                      list.size() );
       
        assertTrue( list.contains( "function1-V2 from rule1" ) );

        ksession.dispose();
        kagent.dispose();
    }

    @Test
    public void testAddModifyQueryIncremental() throws Exception {
   
            String query1 = "";
            query1 += "query \"all the Strings\"\n";
            query1 += "     $strings : String()\n";
            query1 += "end\n";
   
            fileManager.write("rule1.drl", this.createDefaultRule("rule1") );
   
            String xml = "";
            xml += "<change-set xmlns='http://drools.org/drools-5.0/change-set'";
            xml += "    xmlns:xs='http://www.w3.org/2001/XMLSchema-instance'";
            xml += "    xs:schemaLocation='http://drools.org/drools-5.0/change-set http://anonsvn.jboss.org/repos/labs/labs/jbossrules/trunk/drools-api/src/main/resources/change-set-1.0.0.xsd' >";
            xml += "    <add> ";
            xml += "        <resource source='http://localhost:"+this.getPort()+"/rule1.drl' type='DRL' />";
            xml += "    </add> ";
            xml += "</change-set>";
            File fxml = fileManager.write( "changeset.xml",
                                       xml );

            KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
            KnowledgeAgent kagent = this.createKAgent( kbase, false );

            try {
                applyChangeSet( kagent,
                                ResourceFactory.newUrlResource( fxml.toURI().toURL() ) );
            } catch (Exception e) {
                fail( "Knowledge shouldn't fail to compile" );
            }
   
            KnowledgePackage knowledgePackage = kbase.getKnowledgePackage("org.drools.test");
   
            assertNotNull(knowledgePackage);
   
            Rule allTheStringsQuery = ((KnowledgePackageImp) knowledgePackage).getRule("all the Strings");
   
            assertNull(allTheStringsQuery);
   
               
            //we are going to add the query now
            fileManager.write("rule1.drl", this.createDefaultRule("rule1") + " \n " + query1 );
           
            this.scan(kagent);
   
            StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
            List<String> list = new ArrayList<String>();
            ksession.setGlobal("list", list);
            ksession.insert("Some String");
            ksession.insert("Some Other String");
   
            QueryResults queryResults = ksession.getQueryResults("all the Strings");
   
            assertEquals(2, queryResults.size());
   
            Iterator<QueryResultsRow> iterator = queryResults.iterator();
            while (iterator.hasNext()){
                System.out.println("Row= "+iterator.next().get("$strings"));
            }
   
            //we are going to modify the query definition
            String query1V2 = "";
            query1V2 += "query \"all the Strings\"\n";
            query1V2 += "     $strings : String(this == \"Some String\")\n";
            query1V2 += "end\n";
           
            fileManager.write("rule1.drl", this.createDefaultRule("rule1") + " \n " + query1V2 );
           
            this.scan(kagent);
   
            queryResults = ksession.getQueryResults("all the Strings");
   
   
            assertEquals(1, queryResults.size());
            assertEquals("Some String",queryResults.iterator().next().get("$strings"));
   
            ksession.dispose();
            kagent.dispose();
        }

    /**
     * Creates kagent on a .drl file and then modifies the .drl with a malformed
     * rule. After the kbase is reconstructed (with 0 rules), the .drl is modified
     * again with a valid rule.
     * This test tends to prove that JBRULES-2904 is solved
     * @throws Exception
     */
    @Test
    public void testCompilationFailndFixIncremental() throws Exception {
        fileManager.write( "rule1.drl",
                           createDefaultRule( "rule1" ) );

        String xml = "";
        xml += "<change-set xmlns='http://drools.org/drools-5.0/change-set'";
        xml += "    xmlns:xs='http://www.w3.org/2001/XMLSchema-instance'";
        xml += "    xs:schemaLocation='http://drools.org/drools-5.0/change-set http://anonsvn.jboss.org/repos/labs/labs/jbossrules/trunk/drools-api/src/main/resources/change-set-1.0.0.xsd' >";
        xml += "    <add> ";
        xml += "        <resource source='http://localhost:" + this.getPort() + "/rule1.drl' type='DRL' />";
        xml += "    </add> ";
        xml += "</change-set>";
        File fxml = fileManager.write( "changeset.xml",
                                       xml );

        KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
        KnowledgeAgent kagent = this.createKAgent( kbase,
                                                   false );

        kagent.applyChangeSet( ResourceFactory.newUrlResource( fxml.toURI().toURL() ) );

        assertEquals(1,kbase.getKnowledgePackages().iterator().next().getRules().size());
       
        StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
        List<String> list = new ArrayList<String>();
        ksession.setGlobal( "list",
                            list );
        ksession.fireAllRules();

        assertEquals( 1,
                      list.size() );
        assertTrue( list.contains( "rule1" ) );

        list.clear();

        //malformed rule
        fileManager.write( "rule1.drl",
                           createLhsRule("rule1", "String())") );

        try{
            scan( kagent );
            fail("The compilation should fail!");
        }catch (RuntimeException ex){
            //expected expcetion
        }

       
        assertTrue(kbase.getKnowledgePackages().iterator().next().getRules().isEmpty());
       
        //wellformed rule again
        fileManager.write( "rule1.drl",
                           createDefaultRule( "rule1" ) );
       
        scan( kagent );
       
        list.clear();
        ksession.fireAllRules();

        assertEquals( 1,
                      list.size() );
        assertTrue( list.contains( "rule1" ) );

        ksession.dispose();
        kagent.dispose();
    }

    /**
     * Same as {@link #testCompilationFailndFixIncremental() } but with two drl
     * files and only one failing.
     * This test tends to prove that JBRULES-2904 is solved
     * @throws Exception
     */
    @Test
    public void testCompilationFailndFixIncremental2() throws Exception {
        fileManager.write( "rule1.drl",
                           createLhsRule("rule1", "String()") );
        fileManager.write( "rule2.drl",
                           createLhsRule("rule2", "String()") );

        String xml = "";
        xml += "<change-set xmlns='http://drools.org/drools-5.0/change-set'";
        xml += "    xmlns:xs='http://www.w3.org/2001/XMLSchema-instance'";
        xml += "    xs:schemaLocation='http://drools.org/drools-5.0/change-set http://anonsvn.jboss.org/repos/labs/labs/jbossrules/trunk/drools-api/src/main/resources/change-set-1.0.0.xsd' >";
        xml += "    <add> ";
        xml += "        <resource source='http://localhost:" + this.getPort() + "/rule1.drl' type='DRL' />";
        xml += "        <resource source='http://localhost:" + this.getPort() + "/rule2.drl' type='DRL' />";
        xml += "    </add> ";
        xml += "</change-set>";
        File fxml = fileManager.write( "changeset.xml",
                                       xml );

        KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
        KnowledgeAgent kagent = this.createKAgent( kbase,
                                                   false );

        kagent.applyChangeSet( ResourceFactory.newUrlResource( fxml.toURI().toURL() ) );

        assertEquals(2,kbase.getKnowledgePackages().iterator().next().getRules().size());
       
        StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
        List<String> list = new ArrayList<String>();
        ksession.setGlobal( "list",
                            list );
        ksession.insert("Some String");
        ksession.fireAllRules();

        assertEquals( 2,
                      list.size() );
        assertTrue( list.contains( "rule1" ) );
        assertTrue( list.contains( "rule2" ) );

        list.clear();

        //malformed rule
        fileManager.write( "rule1.drl",
                           createLhsRule("rule1", "String())") );

        try{
            scan( kagent );
            fail("The compilation should fail!");
        }catch (RuntimeException ex){
            //expected expcetion
        }

       
        assertEquals(1,kbase.getKnowledgePackages().iterator().next().getRules().size());
        ksession.insert("Some Other String");
        ksession.fireAllRules();
       
        assertEquals( 1,
                      list.size() );
        assertTrue( list.contains( "rule2" ) );
        list.clear();
       
        //wellformed rule again
        fileManager.write( "rule1.drl",
                           createDefaultRule( "rule1" ) );
       
        scan( kagent );
       
        ksession.insert("Yet Another String");
        ksession.fireAllRules();

        assertEquals( 2,
                      list.size() );
        assertTrue( list.contains( "rule1" ) );
        assertTrue( list.contains( "rule2" ) );

        ksession.dispose();
        kagent.dispose();
    }
   
    @Test
    public void testMultiplePackages() throws Exception {
        //One rule in some.pkg package
        File f1 = fileManager.write( "rule1.drl",
                                        createLhsRule("some.pkg","rule1", "String()") );
        //Two rules in some.other.pkg package
        File f2 = fileManager.write( "rule2.drl",
                                        createLhsRule("some.other.pkg",new String[]{"rule2","rule3"}, "String()") );

        String xml = "";
        xml += "<change-set xmlns='http://drools.org/drools-5.0/change-set'";
        xml += "    xmlns:xs='http://www.w3.org/2001/XMLSchema-instance'";
        xml += "    xs:schemaLocation='http://drools.org/drools-5.0/change-set http://anonsvn.jboss.org/repos/labs/labs/jbossrules/trunk/drools-api/src/main/resources/change-set-1.0.0.xsd' >";
        xml += "    <add> ";
        xml += "        <resource source='http://localhost:" + this.getPort() + "/rule1.drl' type='DRL' />";
        xml += "        <resource source='http://localhost:" + this.getPort() + "/rule2.drl' type='DRL' />";
        xml += "    </add> ";
        xml += "</change-set>";
        File fxml = fileManager.write( "changeset.xml",
                                       xml );

        KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
        KnowledgeAgent kagent = this.createKAgent( kbase,
                                                   false );

        kagent.applyChangeSet(ResourceFactory.newUrlResource( fxml.toURI().toURL() ));

        //Did the agent respected the packges?
        assertEquals(2, kbase.getKnowledgePackages().size());
       
        //some.pkg has 1 rule
        KnowledgePackage somePkg = kbase.getKnowledgePackage("some.pkg");
        assertNotNull(somePkg);
        assertEquals(1, somePkg.getRules().size());
        assertEquals("rule1", somePkg.getRules().iterator().next().getName());
       
        //some.other.pkg has 2 rules
        KnowledgePackage someOtherPkg = kbase.getKnowledgePackage("some.other.pkg");
        assertNotNull(someOtherPkg);
        assertEquals(2, someOtherPkg.getRules().size());
        Iterator<Rule> someOtherPkgRules = someOtherPkg.getRules().iterator();
        assertEquals("rule2", someOtherPkgRules.next().getName());
        assertEquals("rule3", someOtherPkgRules.next().getName());
       
        //Delete rule2.drl content
        this.fileManager.deleteFile(f2);
        scan( kagent );
       
        //the empty package remains in the kbase
        assertEquals(2, kbase.getKnowledgePackages().size());
       
        //some.pkg has 1 rule
        somePkg = kbase.getKnowledgePackage("some.pkg");
        assertNotNull(somePkg);
        assertEquals(1, somePkg.getRules().size());
        assertEquals("rule1", somePkg.getRules().iterator().next().getName());
       
        //some.other.pkg is empty
        someOtherPkg = kbase.getKnowledgePackage("some.other.pkg");
        assertNotNull(someOtherPkg);
        assertTrue(someOtherPkg.getRules().isEmpty());
       
       
        //Add 1 more rule in a different package
        File f3 = fileManager.write( "rule3.drl",
                                        createLhsRule("yet.another.pkg","rule4", "String()") );
       
        xml = "";
        xml += "<change-set xmlns='http://drools.org/drools-5.0/change-set'";
        xml += "    xmlns:xs='http://www.w3.org/2001/XMLSchema-instance'";
        xml += "    xs:schemaLocation='http://drools.org/drools-5.0/change-set http://anonsvn.jboss.org/repos/labs/labs/jbossrules/trunk/drools-api/src/main/resources/change-set-1.0.0.xsd' >";
        xml += "    <add> ";
        xml += "        <resource source='http://localhost:" + this.getPort() + "/rule3.drl' type='DRL' />";
        xml += "    </add> ";
        xml += "</change-set>";
       
        this.applyChangeSet(kagent, xml);
       
        //There should be 3 packages now
        assertEquals(3, kbase.getKnowledgePackages().size());
       
        //some.pkg has 1 rule
        somePkg = kbase.getKnowledgePackage("some.pkg");
        assertNotNull(somePkg);
        assertEquals(1, somePkg.getRules().size());
        assertEquals("rule1", somePkg.getRules().iterator().next().getName());
       
        //some.other.pkg is empty
        someOtherPkg = kbase.getKnowledgePackage("some.other.pkg");
        assertNotNull(someOtherPkg);
        assertTrue(someOtherPkg.getRules().isEmpty());
        //yet.another.pkg has 1 rule
        KnowledgePackage yetAnotherPkg = kbase.getKnowledgePackage("yet.another.pkg");
        assertNotNull(yetAnotherPkg);
        assertEquals(1, yetAnotherPkg.getRules().size());
        assertEquals("rule4", yetAnotherPkg.getRules().iterator().next().getName());
       
       
        kagent.dispose();
    }
}
TOP

Related Classes of org.drools.agent.KnowledgeAgentIncrementalChangeSetTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.