@Test
  public void testRuleExecution() throws RepositoryException, RuleExecutionException {
    String path = "/test/ruleset";

    Mockito.when(request.getResourceResolver()).thenReturn(resourceResolver);
    Mockito.when(resourceResolver.adaptTo(Session.class)).thenReturn(session);
    Mockito.when(session.getUserID()).thenReturn("ieb");

    Mockito.when(resourceResolver.getResource(path)).thenReturn(ruleSet);
    Mockito.when(ruleSet.getResourceType()).thenReturn(RuleConstants.SAKAI_RULE_SET);
    Mockito.when(ruleSet.adaptTo(Node.class)).thenReturn(ruleSetNode);
    Mockito.when(context.getBundleContext()).thenReturn(bundleContext);

    Mockito.when(ruleSetNode.getPath()).thenReturn(path);
    Mockito.when(ruleSetNode.getNodes()).thenReturn(nodeIterator);

    // specify the rule processor
    Mockito.when(ruleSetNode.hasProperty(RuleConstants.PROP_SAKAI_RULE_EXECUTION_PREPROCESSOR))
        .thenReturn(true);
    Mockito.when(ruleSetNode.getProperty(RuleConstants.PROP_SAKAI_RULE_EXECUTION_PREPROCESSOR))
        .thenReturn(preprocessorProperty);
    Mockito.when(preprocessorProperty.getString()).thenReturn("message-test-preprocessor");

    // when the service referece is invoked we need to give it out processor
    Mockito.when(reference.getProperty(RuleConstants.PROCESSOR_NAME))
        .thenReturn("message-test-preprocessor");

    RuleExecutionPreProcessor messageRuleExcutionPreProcessor =
        new MesageRuleExcutionPreProcessor();
    Mockito.when(bundleContext.getService(reference)).thenReturn(messageRuleExcutionPreProcessor);

    // turn on debug for this rule execution, just needs the property to exist.
    Mockito.when(ruleSetNode.hasProperty(RuleConstants.PROP_SAKAI_RULE_DEBUG))
        .thenReturn(true, true, false);

    Mockito.when(nodeIterator.hasNext()).thenReturn(true, false, true, false);
    Mockito.when(nodeIterator.nextNode()).thenReturn(packageNode, packageNode);
    Mockito.when(packageNode.getPrimaryNodeType()).thenReturn(packageNodeType);
    Mockito.when(packageNodeType.getName()).thenReturn(NodeType.NT_FILE);

    Mockito.when(packageNode.getPath()).thenReturn(path + "/package1");

    Mockito.when(packageNode.getNode(Node.JCR_CONTENT)).thenReturn(packageFileNode);

    Mockito.when(packageFileNode.getProperty(Property.JCR_LAST_MODIFIED)).thenReturn(property);
    Calendar lastModified = GregorianCalendar.getInstance();
    lastModified.setTimeInMillis(System.currentTimeMillis());
    Calendar lastModifiedLater = GregorianCalendar.getInstance();
    lastModifiedLater.setTimeInMillis(System.currentTimeMillis() + 20000);
    Mockito.when(property.getDate()).thenReturn(lastModified, lastModified, lastModifiedLater);

    Mockito.when(packageFileNode.getProperty(Property.JCR_DATA)).thenReturn(packageFileBody);

    Mockito.when(packageFileBody.getBinary()).thenReturn(binary);

    Mockito.when(binary.getStream())
        .thenAnswer(
            new Answer<InputStream>() {

              public InputStream answer(InvocationOnMock invocation) throws Throwable {
                return this.getClass()
                    .getResourceAsStream(
                        "/SLING-INF/content/var/rules/org.sakaiproject.nakamura.rules/org.sakaiproject.nakamura.rules.example/0.7-SNAPSHOT/org.sakaiproject.nakamura.rules.example-0.7-SNAPSHOT.pkg");
              }
            });

    RuleExecutionServiceImpl res = new RuleExecutionServiceImpl();
    res.activate(context);
    res.bindProcessor(reference);
    Map<String, Object> result =
        res.executeRuleSet(path, request, targetResource, ruleContext, null);

    Assert.assertNotNull(result);
    Assert.assertTrue(result.size() > 0);

    // execute a second time to use the cache.
    result = res.executeRuleSet(path, request, targetResource, ruleContext, null);

    Assert.assertNotNull(result);
    Assert.assertTrue(result.size() > 0);

    // execute a third time time to reload.
    result = res.executeRuleSet(path, request, targetResource, ruleContext, null);

    Assert.assertNotNull(result);
    Assert.assertTrue(result.size() > 0);

    res.deactivate(context);
  }
  @Test
  public void testRuleExecutionFromBundle() throws RepositoryException, RuleExecutionException {
    String path = "/test/ruleset";

    Mockito.when(request.getResourceResolver()).thenReturn(resourceResolver);
    Mockito.when(resourceResolver.adaptTo(Session.class)).thenReturn(session);
    Mockito.when(session.getUserID()).thenReturn("ieb");

    Mockito.when(resourceResolver.getResource(path)).thenReturn(ruleSet);
    Mockito.when(ruleSet.getResourceType()).thenReturn(RuleConstants.SAKAI_RULE_SET);
    Mockito.when(ruleSet.adaptTo(Node.class)).thenReturn(ruleSetNode);
    Mockito.when(context.getBundleContext()).thenReturn(bundleContext);

    Mockito.when(ruleSetNode.getPath()).thenReturn(path);
    Mockito.when(ruleSetNode.getNodes()).thenReturn(nodeIterator);

    // specify the rule processor
    Mockito.when(ruleSetNode.hasProperty(RuleConstants.PROP_SAKAI_RULE_EXECUTION_PREPROCESSOR))
        .thenReturn(true);
    Mockito.when(ruleSetNode.getProperty(RuleConstants.PROP_SAKAI_RULE_EXECUTION_PREPROCESSOR))
        .thenReturn(preprocessorProperty);
    Mockito.when(preprocessorProperty.getString()).thenReturn("message-test-preprocessor");

    // when the service referece is invoked we need to give it out processor
    Mockito.when(reference.getProperty(RuleConstants.PROCESSOR_NAME))
        .thenReturn("message-test-preprocessor");

    RuleExecutionPreProcessor messageRuleExcutionPreProcessor =
        new MesageRuleExcutionPreProcessor();
    Mockito.when(bundleContext.getService(reference)).thenReturn(messageRuleExcutionPreProcessor);

    // turn on debug for this rule execution, just needs the property to exist.
    Mockito.when(ruleSetNode.hasProperty(RuleConstants.PROP_SAKAI_RULE_DEBUG))
        .thenReturn(true, true, false);

    Mockito.when(nodeIterator.hasNext()).thenReturn(true, false, true, false);
    Mockito.when(nodeIterator.nextNode()).thenReturn(packageNode, packageNode);

    // its an nt:unstrucured node
    Mockito.when(packageNode.getPrimaryNodeType()).thenReturn(packageNodeType);
    Mockito.when(packageNodeType.getName()).thenReturn(NodeType.NT_UNSTRUCTURED);

    Mockito.when(packageNode.hasProperty(RuleConstants.PROP_SAKAI_BUNDLE_LOADER_CLASS))
        .thenReturn(true);

    Mockito.when(packageNode.getProperty(RuleConstants.PROP_SAKAI_BUNDLE_LOADER_CLASS))
        .thenReturn(packageBundleClass);
    Mockito.when(packageBundleClass.getString()).thenReturn(BundleLoaderRuleSet.class.getName());

    Mockito.when(packageNode.getPath()).thenReturn(path + "/package1");

    Mockito.when(packageNode.getProperty(Property.JCR_LAST_MODIFIED)).thenReturn(property);
    Calendar lastModified = GregorianCalendar.getInstance();
    lastModified.setTimeInMillis(System.currentTimeMillis());
    Calendar lastModifiedLater = GregorianCalendar.getInstance();
    lastModifiedLater.setTimeInMillis(System.currentTimeMillis() + 20000);
    Mockito.when(property.getDate()).thenReturn(lastModified, lastModified, lastModifiedLater);

    RuleExecutionServiceImpl res = new RuleExecutionServiceImpl();
    res.activate(context);
    res.bindProcessor(reference);
    Map<String, Object> result =
        res.executeRuleSet(path, request, targetResource, ruleContext, null);

    Assert.assertNotNull(result);
    Assert.assertTrue(result.size() > 0);

    // execute a second time to use the cache.
    result = res.executeRuleSet(path, request, targetResource, ruleContext, null);

    Assert.assertNotNull(result);
    Assert.assertTrue(result.size() > 0);

    // execute a third time time to reload.
    result = res.executeRuleSet(path, request, targetResource, ruleContext, null);

    Assert.assertNotNull(result);
    Assert.assertTrue(result.size() > 0);

    res.deactivate(context);
  }