

package gov.va.med.cds.work;


import gov.va.med.cds.junit.runners.Suite;
import gov.va.med.cds.junit.runners.SuiteAwareRunner;
import gov.va.med.cds.transaction.SerialWorkManager;
import gov.va.med.cds.transaction.WorkManagerInterface;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;

import commonj.work.Work;
import commonj.work.WorkEvent;
import commonj.work.WorkItem;

@RunWith(SuiteAwareRunner.class)
public class MultiThreadedWorkManagerTest
{

    private static final int NUM_THREADS = 4;
    private WorkManagerInterface multiThreadedWorkManager = new MultiThreadedWorkManager( new WorkQueue() );
    private WorkManagerInterface serialWorkManager = new SerialWorkManager();


    @Test
    @Suite( groups = { "checkintest" } )
    public void testMultiThreadedWorkManager( ) throws Exception
    {
        Assert.assertNotNull( multiThreadedWorkManager );

        List<WorkItem> pendingWork = new ArrayList<WorkItem>();
        for ( int i = 0; i < NUM_THREADS; i++ )
        {
            // schedule work
            WorkItem workItem = multiThreadedWorkManager.schedule( new BusyWork() );

            // collect the pending work
            pendingWork.add( workItem );
        }

        // wait for all work to be completed
        multiThreadedWorkManager.waitForAll( pendingWork );
        
        Assert.assertTrue( pendingWork.size() == NUM_THREADS );
        
        for(WorkItem wi: pendingWork){
            Assert.assertTrue(wi.getStatus() == WorkEvent.WORK_COMPLETED); 
            Assert.assertFalse( wi.getResult().isDaemon());
        }
    }
    
    @Test
    @Suite( groups = { "checkintest" } )
    public void testSerialWorkManager( ) throws Exception
    {
        Assert.assertNotNull( serialWorkManager );

        List<WorkItem> pendingWork = new ArrayList<WorkItem>();
        for ( int i = 0; i < NUM_THREADS; i++ )
        {
            // schedule work
            WorkItem workItem = serialWorkManager.schedule(new BusyWork());

            // collect the pending work
            pendingWork.add( workItem );
        }

        // wait for all work to be completed
        serialWorkManager.waitForAll( pendingWork );
       
        Assert.assertTrue( pendingWork.size() == NUM_THREADS );
        
        for(WorkItem wi: pendingWork){
            Assert.assertTrue(wi.getStatus() == WorkEvent.WORK_COMPLETED); 
            Assert.assertFalse( wi.getResult().isDaemon());
        }
    }

    
class BusyWork implements Work {

    private static final int MAX_WAIT_TIME = 3;
    @Override
    public void run( )
    {
        try
        {
            int random = new Random().nextInt( MAX_WAIT_TIME );
            Thread.sleep( random * 1000 );
        }
        catch ( InterruptedException e )
        {
            e.printStackTrace();
        }
    }
    @Override
    public void release( )
    {
    }

    @Override
    public boolean isDaemon( )
    {
        return false;
    }    
}    

}
