Index: src/test/java/org/jbpm/test/timer/TimerTest.java
===================================================================
--- src/test/java/org/jbpm/test/timer/TimerTest.java	(revision 6100)
+++ src/test/java/org/jbpm/test/timer/TimerTest.java	(working copy)
@@ -22,7 +22,6 @@
 package org.jbpm.test.timer;
 
 import java.util.Calendar;
-import java.util.Date;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -34,9 +33,9 @@
 import org.jbpm.api.job.Job;
 import org.jbpm.api.listener.EventListener;
 import org.jbpm.api.listener.EventListenerExecution;
+import org.jbpm.pvm.internal.util.Clock;
 import org.jbpm.test.JbpmTestCase;
 
-
 /**
  * @author Tom Baeyens
  * @author Ronald Van Kuijk
@@ -198,116 +197,118 @@
   }
   
   public void testTimerELCalendarAdd() {
-	    deployJpdlXmlString(
-	      "<process name='Insurance claim' key='ICL'>" +
-	      "  <start>" +
-	      "    <transition to='a' />" +
-	      "  </start>" +
-	      "  <state name='a'>" +
-	      "    <transition to='b' />" +
-	      "    <transition name='timeout' to='escalate'>" +
-	      "      <timer duedate='#{proc_var} + 5 days' />" +
-	      "    </transition>" +
-	      "  </state>" +
-	      "  <state name='b' />" +
-	      "  <end name='escalate' />" +
-	      "</process>"
-	    );
-		    
-	    Map<String, Object> proc_vars = new HashMap<String, Object>();
-	    Calendar cal = Calendar.getInstance();
-	    cal.add(Calendar.DAY_OF_MONTH, 6);
-	    proc_vars.put("proc_var", cal);
-	    ProcessInstance processInstance = executionService.startProcessInstanceByKey("ICL", proc_vars, "82436");
-		    
-	    Job job = managementService.createJobQuery()
-	      .processInstanceId(processInstance.getId())
-	      .uniqueResult();
-	    
-	    Calendar jobDate = Calendar.getInstance();
-	    jobDate.setTime(job.getDuedate());
-	    
-	    assertEquals(cal.get(Calendar.DAY_OF_MONTH) + 5 , jobDate.get(Calendar.DAY_OF_MONTH));
-	    
-	    managementService.executeJob(job.getId());
-	    assertProcessInstanceEnded(processInstance);
-	  }
-  
+    deployJpdlXmlString(
+      "<process name='Insurance claim' key='ICL'>" +
+      "  <start>" +
+      "    <transition to='a' />" +
+      "  </start>" +
+      "  <state name='a'>" +
+      "    <transition to='b' />" +
+      "    <transition name='timeout' to='escalate'>" +
+      "      <timer duedate='#{proc_var} + 5 days' />" +
+      "    </transition>" +
+      "  </state>" +
+      "  <state name='b' />" +
+      "  <end name='escalate' />" +
+      "</process>"
+    );
+
+    Map<String, Object> proc_vars = new HashMap<String, Object>();
+    Calendar cal = Calendar.getInstance();
+    cal.add(Calendar.DAY_OF_MONTH, 6);
+    proc_vars.put("proc_var", cal);
+    ProcessInstance processInstance = executionService.startProcessInstanceByKey("ICL", proc_vars, "82436");
+
+    Job job = managementService.createJobQuery()
+      .processInstanceId(processInstance.getId())
+      .uniqueResult();
+
+    Calendar jobDate = Calendar.getInstance();
+    jobDate.setTime(job.getDuedate());
+
+    cal.add(Calendar.DAY_OF_MONTH, 5);
+    assertEquals(cal.get(Calendar.DAY_OF_MONTH), jobDate.get(Calendar.DAY_OF_MONTH));
+
+    managementService.executeJob(job.getId());
+    assertProcessInstanceEnded(processInstance);
+  }
+
   public void testTimerELCalendarSubtract() {
-	    deployJpdlXmlString(
-	      "<process name='Insurance claim' key='ICL'>" +
-	      "  <start>" +
-	      "    <transition to='a' />" +
-	      "  </start>" +
-	      "  <state name='a'>" +
-	      "    <transition to='b' />" +
-	      "    <transition name='timeout' to='escalate'>" +
-	      "      <timer duedate='#{proc_var} - 5 days' />" +
-	      "    </transition>" +
-	      "  </state>" +
-	      "  <state name='b' />" +
-	      "  <end name='escalate' />" +
-	      "</process>"
-	    );
-		    
-	    Map<String, Object> proc_vars = new HashMap<String, Object>();
-	    Calendar cal = Calendar.getInstance();
-	    cal.add(Calendar.DAY_OF_MONTH, 6);
-	    proc_vars.put("proc_var", cal);
-	    ProcessInstance processInstance = executionService.startProcessInstanceByKey("ICL", proc_vars, "82436");
-		    
-	    Job job = managementService.createJobQuery()
-	      .processInstanceId(processInstance.getId())
-	      .uniqueResult();
-	    
-	    Calendar jobDate = Calendar.getInstance();
-	    jobDate.setTime(job.getDuedate());
-	    
-	    // 6 days from now minus 5 days is tomorrow so subtract 5 from the original added 6.
-	    assertEquals(cal.get(Calendar.DAY_OF_MONTH) -5 , jobDate.get(Calendar.DAY_OF_MONTH));
-	    
-	    managementService.executeJob(job.getId());
-	    assertProcessInstanceEnded(processInstance);
-	  }
-  
-  
+    deployJpdlXmlString(
+      "<process name='Insurance claim' key='ICL'>" +
+      "  <start>" +
+      "    <transition to='a' />" +
+      "  </start>" +
+      "  <state name='a'>" +
+      "    <transition to='b' />" +
+      "    <transition name='timeout' to='escalate'>" +
+      "      <timer duedate='#{proc_var} - 5 days' />" +
+      "    </transition>" +
+      "  </state>" +
+      "  <state name='b' />" +
+      "  <end name='escalate' />" +
+      "</process>"
+    );
+
+    Map<String, Object> proc_vars = new HashMap<String, Object>();
+    Calendar cal = Calendar.getInstance();
+    cal.add(Calendar.DAY_OF_MONTH, 6);
+    
+    proc_vars.put("proc_var", cal);
+    ProcessInstance processInstance = executionService.startProcessInstanceByKey("ICL", proc_vars, "82436");
+
+    Job job = managementService.createJobQuery()
+      .processInstanceId(processInstance.getId())
+      .uniqueResult();
+
+    Calendar jobDate = Calendar.getInstance();
+    jobDate.setTime(job.getDuedate());
+
+    // 6 days from now minus 5 days is tomorrow so subtract 5 from the original added 6.
+    cal.add(Calendar.DAY_OF_MONTH, -5);
+    assertEquals(cal.get(Calendar.DAY_OF_MONTH) , jobDate.get(Calendar.DAY_OF_MONTH));
+
+    managementService.executeJob(job.getId());
+    assertProcessInstanceEnded(processInstance);
+  }
+
   public void testTimerELCalendarAddBusiness() {
-	    deployJpdlXmlString(
-	      "<process name='Insurance claim' key='ICL'>" +
-	      "  <start>" +
-	      "    <transition to='a' />" +
-	      "  </start>" +
-	      "  <state name='a'>" +
-	      "    <transition to='b' />" +
-	      "    <transition name='timeout' to='escalate'>" +
-	      "      <timer duedate='#{proc_var} + 5 business days' />" +
-	      "    </transition>" +
-	      "  </state>" +
-	      "  <state name='b' />" +
-	      "  <end name='escalate' />" +
-	      "</process>"
-	    );
-		    
-	    Map<String, Object> proc_vars = new HashMap<String, Object>();
-	    Calendar cal = Calendar.getInstance();
-	    cal.set(2010, 01, 12, 12, 00, 00); // 12 feb 2010 noon
-	    proc_vars.put("proc_var", cal);
-	    ProcessInstance processInstance = executionService.startProcessInstanceByKey("ICL", proc_vars, "82436");
-		    
-	    Job job = managementService.createJobQuery()
-	      .processInstanceId(processInstance.getId())
-	      .uniqueResult();
-	    
-	    Calendar jobDate = Calendar.getInstance();
-	    jobDate.setTime(job.getDuedate());
-	    
-	    // 12 feb is friday, 5 businessdays further is friday 19th
-	    assertEquals(19 , jobDate.get(Calendar.DAY_OF_MONTH));
-	    
-	    managementService.executeJob(job.getId());
-	    assertProcessInstanceEnded(processInstance);
-	  }
-  
+    deployJpdlXmlString(
+      "<process name='Insurance claim' key='ICL'>" +
+      "  <start>" +
+      "    <transition to='a' />" +
+      "  </start>" +
+      "  <state name='a'>" +
+      "    <transition to='b' />" +
+      "    <transition name='timeout' to='escalate'>" +
+      "      <timer duedate='#{proc_var} + 5 business days' />" +
+      "    </transition>" +
+      "  </state>" +
+      "  <state name='b' />" +
+      "  <end name='escalate' />" +
+      "</process>"
+    );
+
+    Map<String, Object> proc_vars = new HashMap<String, Object>();
+    Calendar cal = Calendar.getInstance();
+    cal.set(2010, 01, 12, 12, 00, 00); // 12 feb 2010 noon
+    proc_vars.put("proc_var", cal);
+    ProcessInstance processInstance = executionService.startProcessInstanceByKey("ICL", proc_vars, "82436");
+
+    Job job = managementService.createJobQuery()
+      .processInstanceId(processInstance.getId())
+      .uniqueResult();
+
+    Calendar jobDate = Calendar.getInstance();
+    jobDate.setTime(job.getDuedate());
+
+    // 12 feb is friday, 5 businessdays further is friday 19th
+    assertEquals(19 , jobDate.get(Calendar.DAY_OF_MONTH));
+
+    managementService.executeJob(job.getId());
+    assertProcessInstanceEnded(processInstance);
+  }
+
   public void testTimerELFail() {
     deployJpdlXmlString(
       "<process name='Insurance claim' key='ICL'>" +
@@ -328,65 +329,145 @@
     Map<String, Object> proc_vars = new HashMap<String, Object>();
     proc_vars.put("proc_var", new Long(0));
     try {
-      ProcessInstance processInstance = executionService.startProcessInstanceByKey("ICL", proc_vars, "82436");
+      executionService.startProcessInstanceByKey("ICL", proc_vars, "82436");
       fail("Should not happen, exception expected");
     } catch (Exception e) {}
   }
 
-  public void testTimerELSubtractBusinessFail() {
-	    deployJpdlXmlString(
-	      "<process name='Insurance claim' key='ICL'>" +
-	      "  <start>" +
-	      "    <transition to='a' />" +
-	      "  </start>" +
-	      "  <state name='a'>" +
-	      "    <transition to='b' />" +
-	      "    <transition name='timeout' to='escalate'>" +
-	      "      <timer duedate='#{proc_var} - 6 business days' />" +
-	      "    </transition>" +
-	      "  </state>" +
-	      "  <state name='b' />" +
-	      "  <end name='escalate' />" +
-	      "</process>"
-	    );
-	    
-	    Map<String, Object> proc_vars = new HashMap<String, Object>();
-	    Calendar cal = Calendar.getInstance();
-	    cal.set(2010, 01, 12, 12, 00, 00); // 12 feb 2010 noon
-	    proc_vars.put("proc_var", cal);
-	    try {
-	      ProcessInstance processInstance = executionService.startProcessInstanceByKey("ICL", proc_vars, "82436");
-	      fail("Should not happen, exception expected");
-	    } catch (Exception e) {}
-  }
+  public void testTimerELSubtractBusiness() {
+    deployJpdlXmlString(
+      "<process name='Insurance claim' key='ICL'>" +
+      "  <start>" +
+      "    <transition to='a' />" +
+      "  </start>" +
+      "  <state name='a'>" +
+      "    <transition to='b' />" +
+      "    <transition name='timeout' to='escalate'>" +
+      "      <timer duedate='#{proc_var} - 5 business days' />" +
+      "    </transition>" +
+      "  </state>" +
+      "  <state name='b' />" +
+      "  <end name='escalate' />" +
+      "</process>"
+    );
+ 
+    Map<String, Object> proc_vars = new HashMap<String, Object>();
+    Calendar cal = Calendar.getInstance();
+    cal.set(2010, 01, 19, 12, 00, 00); // 19 feb 2010 noon
+    proc_vars.put("proc_var", cal);
+    ProcessInstance processInstance = executionService.startProcessInstanceByKey("ICL", proc_vars, "82436");
+
+    Job job = managementService.createJobQuery()
+      .processInstanceId(processInstance.getId())
+      .uniqueResult();
+
+    Calendar jobDate = Calendar.getInstance();
+    jobDate.setTime(job.getDuedate());
+
+    // 19 feb is friday, 5 businessdays before is friday 12th
+    assertEquals(12 , jobDate.get(Calendar.DAY_OF_MONTH));
+
+    managementService.executeJob(job.getId());
+    assertProcessInstanceEnded(processInstance);	  
+  }  
   
+  public void testTimerELSubtractBusinessLeap() {
+    deployJpdlXmlString(
+      "<process name='Insurance claim' key='ICL'>" +
+      "  <start>" +
+      "    <transition to='a' />" +
+      "  </start>" +
+      "  <state name='a'>" +
+      "    <transition to='b' />" +
+      "    <transition name='timeout' to='escalate'>" +
+      "      <timer duedate='#{proc_var} - 5 business days' />" +
+      "    </transition>" +
+      "  </state>" +
+      "  <state name='b' />" +
+      "  <end name='escalate' />" +
+      "</process>"
+    );
+	 
+	Map<String, Object> proc_vars = new HashMap<String, Object>();
+    Calendar cal = Calendar.getInstance();
+    cal.set(2012, 03, 5, 12, 00, 00); // 5 march 2012 noon
+    proc_vars.put("proc_var", cal);
+    ProcessInstance processInstance = executionService.startProcessInstanceByKey("ICL", proc_vars, "82436");
+
+    Job job = managementService.createJobQuery().processInstanceId(processInstance.getId()).uniqueResult();
+
+    Calendar jobDate = Calendar.getInstance();
+    jobDate.setTime(job.getDuedate());
+
+    // 5 mar is monday, 5 businessdays before is monday feb 27th (29-02-12 is leap day)
+    assertEquals(27, jobDate.get(Calendar.DAY_OF_MONTH));
+
+    managementService.executeJob(job.getId());
+    assertProcessInstanceEnded(processInstance);
+  }  
+  
+  public void testTimerELSubtractBusinessMonthBoundary() {
+    deployJpdlXmlString(
+      "<process name='Insurance claim' key='ICL'>" +
+      "  <start>" +
+      "    <transition to='a' />" +
+      "  </start>" +
+      "  <state name='a'>" +
+      "    <transition to='b' />" +
+      "    <transition name='timeout' to='escalate'>" +
+      "      <timer duedate='#{proc_var} - 10 business days' />" +
+      "    </transition>" +
+      "  </state>" +
+      "  <state name='b' />" +
+      "  <end name='escalate' />" +
+      "</process>"
+    );
+     
+    Map<String, Object> proc_vars = new HashMap<String, Object>();
+    Calendar cal = Calendar.getInstance();
+    cal.set(2012, 02, 13, 21, 00, 00); // 13 feb 2012 noon
+    proc_vars.put("proc_var", cal);
+    ProcessInstance processInstance = executionService.startProcessInstanceByKey("ICL", proc_vars, "82436");
+
+    Job job = managementService.createJobQuery().processInstanceId(processInstance.getId()).uniqueResult();
+
+    Calendar jobDate = Calendar.getInstance();
+    jobDate.setTime(job.getDuedate());
+
+    // 5 mar is monday, 5 businessdays before is monday feb 27th (29-02-12 is leap day)
+    assertEquals(30, jobDate.get(Calendar.DAY_OF_MONTH));
+
+    managementService.executeJob(job.getId());
+    assertProcessInstanceEnded(processInstance);
+  }   
+
   public void testTimerELSubtractPastFail() {
-	    deployJpdlXmlString(
-	      "<process name='Insurance claim' key='ICL'>" +
-	      "  <start>" +
-	      "    <transition to='a' />" +
-	      "  </start>" +
-	      "  <state name='a'>" +
-	      "    <transition to='b' />" +
-	      "    <transition name='timeout' to='escalate'>" +
-	      "      <timer duedate='#{proc_var} - 3 days' />" +
-	      "    </transition>" +
-	      "  </state>" +
-	      "  <state name='b' />" +
-	      "  <end name='escalate' />" +
-	      "</process>"
-	    );
-	    
-	    Map<String, Object> proc_vars = new HashMap<String, Object>();
-	    Calendar cal = Calendar.getInstance();
-	    cal.add(Calendar.DAY_OF_MONTH, 2);
-	    proc_vars.put("proc_var", cal);
-	    try {
-	      ProcessInstance processInstance = executionService.startProcessInstanceByKey("ICL", proc_vars, "82436");
-	      fail("Should not happen, exception expected");
-	    } catch (Exception e) {}
-}
-  
+    deployJpdlXmlString(
+      "<process name='Insurance claim' key='ICL'>" +
+      "  <start>" +
+      "    <transition to='a' />" +
+      "  </start>" +
+      "  <state name='a'>" +
+      "    <transition to='b' />" +
+      "    <transition name='timeout' to='escalate'>" +
+      "      <timer duedate='#{proc_var} - 3 days' />" +
+      "    </transition>" +
+      "  </state>" +
+      "  <state name='b' />" +
+      "  <end name='escalate' />" +
+      "</process>"
+    );
+
+    Map<String, Object> proc_vars = new HashMap<String, Object>();
+    Calendar cal = Calendar.getInstance();
+    cal.add(Calendar.DAY_OF_MONTH, 2);
+    proc_vars.put("proc_var", cal);
+    try {
+      executionService.startProcessInstanceByKey("ICL", proc_vars, "82436");
+      fail("Should not happen, exception expected");
+    } catch (Exception e) {}
+  }
+
   public void testTimerTimeoutCustom() {
     deployJpdlXmlString(TEST_PROCESS_CUSTOM);
 
@@ -411,7 +492,6 @@
     assertProcessInstanceActive(processInstance);
     executionService.signalExecutionById(processInstance.getExecution("a").getId());
     assertActivityActive(processInstance.getId(), "b");
-
   }
 
   public void testTimerSignalCustom() {
