/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you 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.apache.wiki.workflow;
import java.math.BigDecimal;
import java.security.Principal;
import java.util.Date;
import junit.framework.TestCase;
import org.apache.wiki.api.exceptions.WikiException;
import org.apache.wiki.auth.GroupPrincipal;
import org.apache.wiki.auth.WikiPrincipal;
public class WorkflowTest extends TestCase
{
Workflow w;
Task initTask;
Decision decision;
Task finishTask;
String ATTR = "TestAttribute";
protected void setUp() throws Exception
{
super.setUp();
// Create workflow; owner is test user
w = new Workflow("workflow.myworkflow", new WikiPrincipal("Owner1"));
// Create custom initialization task
initTask = new TaskTest.NormalTask(w);
// Create finish task
finishTask = new TaskTest.NormalTask(w);
// Create an intermetidate decision step
Principal actor = new GroupPrincipal("Admin");
decision = new SimpleDecision(w, "decision.AdminDecision", actor);
// Hook the steps together
initTask.addSuccessor(Outcome.STEP_COMPLETE, decision);
decision.addSuccessor(Outcome.DECISION_APPROVE, finishTask);
// Stash page name as message attribute
w.addMessageArgument("MyPage");
// Set workflow's first step
w.setFirstStep(initTask);
}
public void testWorkflow()
{
// Make sure everything is set to their proper default values
assertNull(w.getCurrentStep());
assertNull(w.getCurrentActor());
assertEquals(0, w.getHistory().size());
assertEquals(Workflow.ID_NOT_SET, w.getId());
assertNull(w.getWorkflowManager());
assertEquals(new WikiPrincipal("Owner1"), w.getOwner());
assertEquals(Workflow.CREATED, w.getCurrentState());
assertEquals(Workflow.TIME_NOT_SET, w.getStartTime());
assertEquals(Workflow.TIME_NOT_SET, w.getEndTime());
}
public void testSetWorkflowManager()
{
assertNull(w.getWorkflowManager());
WorkflowManager m = new WorkflowManager();
w.setWorkflowManager(m);
assertEquals(m, w.getWorkflowManager());
}
public void testGetSetAttribute()
{
assertNull(w.getAttribute(ATTR));
w.setAttribute(ATTR, "Test String");
assertNotNull(w.getAttribute(ATTR));
assertEquals("Test String", w.getAttribute(ATTR));
}
public void testGetMessageArgs() throws WikiException
{
Object[] args;
// Before start, arg1=Owner1, arg2=- (no current actor), arg3=MyPage
args = w.getMessageArguments();
assertEquals("Owner1", args[0]);
assertEquals("-", args[1]);
assertEquals("MyPage", args[2]);
// After start (at Decision), arg1=Owner1, arg2=Admin, arg3=MyPage
w.start();
args = w.getMessageArguments();
assertEquals("Owner1", args[0]);
assertEquals("Admin", args[1]);
assertEquals("MyPage", args[2]);
// After end, arg1=Owner1, arg2=-, arg3=MyPage
decision.decide(Outcome.DECISION_APPROVE);
args = w.getMessageArguments();
assertEquals("Owner1", args[0]);
assertEquals("-", args[1]);
assertEquals("MyPage", args[2]);
}
public void testGetMessageArgObjects()
{
// Try passing some valid object types: Date, Number
w.addMessageArgument(new Date());
w.addMessageArgument(new Integer(1));
w.addMessageArgument(new Double(2));
w.addMessageArgument(new BigDecimal(3.14));
// Try passing an invalid one: e.g., a Workflow (it should fail)
try
{
w.addMessageArgument(w);
}
catch (IllegalArgumentException e)
{
// Swallow
return;
}
// We should never get here
fail("Illegal argument passed...");
}
public void testGetMessageKey()
{
assertEquals("workflow.myworkflow", w.getMessageKey());
}
public void testGetOwner()
{
assertEquals(new WikiPrincipal("Owner1"), w.getOwner());
}
public void testStart() throws WikiException
{
assertFalse(w.isStarted());
w.start();
assertTrue(w.isStarted());
}
public void testWaitstate() throws WikiException
{
w.start();
// Default workflow should have hit the Decision step and put itself
// into WAITING
assertEquals(Workflow.WAITING, w.getCurrentState());
}
public void testRestart() throws WikiException
{
w.start();
// Default workflow should have hit the Decision step and put itself
// into WAITING
assertEquals(Workflow.WAITING, w.getCurrentState());
w.restart();
assertEquals(Workflow.WAITING, w.getCurrentState());
}
public void testAbortBeforeStart() throws WikiException
{
// Workflow hasn't been started yet
assertFalse(w.isAborted());
w.abort();
assertTrue(w.isAborted());
// Try to start anyway
try
{
w.start();
}
catch (IllegalStateException e)
{
// Swallow
return;
}
// We should never get here
fail("Workflow allowed itself to be started even though it was aborted!");
}
public void testAbortDuringWait() throws WikiException
{
// Start workflow, then abort while in WAITING state
assertFalse(w.isAborted());
w.start();
w.abort();
assertTrue(w.isAborted());
// Try to restart anyway
try
{
w.restart();
}
catch (IllegalStateException e)
{
// Swallow
return;
}
// We should never get here
fail("Workflow allowed itself to be re-started even though it was aborted!");
}
public void testAbortAfterCompletion() throws WikiException
{
// Start workflow, then abort after completion
assertFalse(w.isAborted());
w.start();
Decision d = (Decision) w.getCurrentStep();
d.decide(Outcome.DECISION_APPROVE);
// Try to abort anyway
try
{
w.abort();
assertTrue(w.isAborted());
}
catch (IllegalStateException e)
{
// Swallow
return;
}
// We should never get here
fail("Workflow allowed itself to be aborted even though it was completed!");
}
public void testCurrentState() throws WikiException
{
assertEquals(Workflow.CREATED, w.getCurrentState());
w.start();
assertEquals(Workflow.WAITING, w.getCurrentState());
Decision d = (Decision) w.getCurrentStep();
d.decide(Outcome.DECISION_APPROVE);
assertEquals(Workflow.COMPLETED, w.getCurrentState());
}
public void testCurrentStep() throws WikiException
{
assertNull(w.getCurrentStep());
w.start();
// Workflow stops at the decision step
assertEquals(decision, w.getCurrentStep());
Decision d = (Decision) w.getCurrentStep();
d.decide(Outcome.DECISION_APPROVE);
// After we decide, it blows through step 3 and leaves us with a null
// step (done)
assertNull(w.getCurrentStep());
}
public void testPreviousStep() throws WikiException
{
// If not started, no previous steps available for anything
assertNull(w.getPreviousStep());
assertEquals(null, w.previousStep(initTask));
assertEquals(null, w.previousStep(decision));
assertEquals(null, w.previousStep(finishTask));
// Once we start, initTask and decisions' predecessors are known, but
// finish task is indeterminate
w.start();
assertEquals(null, w.previousStep(initTask));
assertEquals(initTask, w.previousStep(decision));
assertEquals(null, w.previousStep(finishTask));
// Once we decide, the finish task returns the correct predecessor
Decision d = (Decision) w.getCurrentStep();
d.decide(Outcome.DECISION_APPROVE);
assertEquals(null, w.previousStep(initTask));
assertEquals(initTask, w.previousStep(decision));
assertEquals(decision, w.previousStep(finishTask));
}
public void testCurrentActor() throws WikiException
{
// Before starting, actor should be null
assertNull(w.getCurrentActor());
// After starting, actor should be GroupPrincipal Admin
w.start();
assertEquals(new GroupPrincipal("Admin"), w.getCurrentActor());
// After decision, actor should be null again
Decision d = (Decision) w.getCurrentStep();
d.decide(Outcome.DECISION_APPROVE);
assertNull(w.getCurrentActor());
}
public void testHistory() throws WikiException
{
assertEquals(0, w.getHistory().size());
w.start();
assertEquals(2, w.getHistory().size());
Decision d = (Decision) w.getCurrentStep();
d.decide(Outcome.DECISION_APPROVE);
assertEquals(3, w.getHistory().size());
}
public void testGetStartTime() throws WikiException
{
// Start time should be not be set until we start the workflow
assertEquals(Workflow.TIME_NOT_SET, w.getStartTime());
w.start();
assertFalse(Workflow.TIME_NOT_SET == w.getStartTime());
Decision d = (Decision) w.getCurrentStep();
d.decide(Outcome.DECISION_APPROVE);
assertFalse(Workflow.TIME_NOT_SET == w.getStartTime());
}
public void testGetEndTime() throws WikiException
{
// End time should be not set until we finish all 3 steps
assertEquals(Workflow.TIME_NOT_SET, w.getEndTime());
w.start();
assertEquals(Workflow.TIME_NOT_SET, w.getEndTime());
Decision d = (Decision) w.getCurrentStep();
d.decide(Outcome.DECISION_APPROVE);
assertFalse(Workflow.TIME_NOT_SET == w.getEndTime());
}
public void testIsCompleted() throws WikiException
{
// Workflow isn't completed until we finish all 3 steps
assertFalse(w.isCompleted());
w.start();
assertFalse(w.isCompleted());
Decision d = (Decision) w.getCurrentStep();
d.decide(Outcome.DECISION_APPROVE);
assertTrue(w.isCompleted());
}
public void testIsStarted() throws WikiException
{
assertFalse(w.isStarted());
w.start();
assertTrue(w.isStarted());
}
public void testStartTwice() throws WikiException
{
w.start();
try
{
w.start();
}
catch (IllegalStateException e)
{
// Swallow
return;
}
// We should never get here
fail("Workflow allowed itself to be started twice!");
}
public void testSetId()
{
assertEquals(Workflow.ID_NOT_SET, w.getId());
w.setId(1001);
assertEquals(1001, w.getId());
}
}