/*******************************************************************************
 * Copyright (c) 2010 Mikhail Garber.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Lesser Public License (LGPL)
 * which accompanies this distribution
 * 
 * Contributors:
 *     Mikhail Garber - initial API and implementation
 ******************************************************************************/
package plumber;

import java.util.Calendar;

import junit.framework.Assert;

import org.junit.After;
import org.junit.Test;

import plumber.model.Flow;

/**
 * main test of the package, exercises basic functionality of the system
 * several differently-configured subclasses exist.
 * 
 * @author mgarber
 *
 */
public abstract class CompleteTest extends BaseTest {

	protected static Flow flow;
	
	/**
	 * test basic functionlity, see inline comments
	 * @throws Exception
	 */
	@Test
	public void testFlow() throws Exception {
		
		// create and populate test context
		TestContext contextO =  new TestContext();		
		contextO.setValue(5);
		
		// submit new workflow to Coordinator and obtain request id
		String context = converter.toStorableString(contextO);
		String rid = getCoordinator().submitWork("unittests", context, "testflow");
		System.out.println("rid:" + rid);
		
		// wait for work flow to complete and obtain context object after
		// it went thru all the steps in the flow
		contextO = waitForComplete(getCoordinator(), rid, 5);
		
		// 5 is odd, so the final result is 5*3 ("triple" step ran)
		Assert.assertEquals(15, contextO.getValue());
		// workflow did not fail
		Assert.assertFalse(getCoordinator().checkFailed(rid));
		Assert.assertTrue(getCoordinator().checkComplete(rid));
		
		// now reset context with value of 6
		contextO.setValue(6);
		
		// submit new workflow
		context = converter.toStorableString(contextO);
		rid = getCoordinator().submitWork("unittests", context, "testflow");
		System.out.println("rid:" + rid);
		
		// wait for completion
		contextO = waitForComplete(getCoordinator(), rid, 5);
		
		// 6 is even, so the result is 6*2 ("double" step ran)
		Assert.assertEquals(12, contextO.getValue());

	}
	
	
	/**
	 * test ability to schedule work flow execution and
	 * ability to suspend/resume stuck workflows.
	 * See inline comments.
	 * @throws InterruptedException
	 */
	@Test
	public void testSuspendEtc() throws InterruptedException {
		
		// create initial context
		TestContext context1 =  new TestContext();		
		context1.setValue(6);

		// create another context
		TestContext context2 =  new TestContext();		
		context2.setValue(5);
		
		// create calendar object set 3 seconds in the future
		Calendar cal = Calendar.getInstance();
		cal.add(Calendar.SECOND, 3);
		
		// count all work items in this namespace
		int all = getCoordinator().getAll("unittests", 100).size();
		
		// submit two new workflows scheduled in the future
		String rid1 = getCoordinator().submitWork("unittests",
				converter.toStorableString(context1), "testflow", cal.getTime());
		String rid2 = getCoordinator().submitWork("unittests",
				converter.toStorableString(context2), "testflow", cal.getTime());
		
		// now, total number of work items is what-it-was-before + 2
		Assert.assertEquals("all:" + getCoordinator().getAll("unittests", 100), 
				all + 2, getCoordinator().getAll("unittests", 100).size());
		
		// since workflow 1 is scheduled but not executed (status AVAILABLE),
		// we can suspend it
		Assert.assertTrue(getCoordinator().suspend(rid1));
		
		// wait 5 seconds
		Thread.sleep(5000);
		
		// second workflow executed, wait for its completion
		context2 = waitForComplete(getCoordinator(), rid2, 5);
		
		// verify result
		Assert.assertEquals(15, context2.getValue());
		
		
		// meanwhile, first workflow is neither completed, nor failed
		// because it is suspended
		Assert.assertFalse(getCoordinator().checkComplete(rid1));
		Assert.assertFalse(getCoordinator().checkFailed(rid1));
		
		
		// now resume first workflow
		Assert.assertTrue(getCoordinator().resume(rid1));
		
		// wait for its completion and check result
		context1 = waitForComplete(getCoordinator(), rid1, 5);
		Assert.assertEquals(12, context1.getValue());
	}

	@After
	public void shutdown() {
		
	}
	
	
}
