gt:         final List<String> sequence = new Vector<String>();
context: /*******************************************************************************
   * This file is part of OpenNMS(R).
   *
   * Copyright (C) 2009-2012 The OpenNMS Group, Inc.
   * OpenNMS(R) is Copyright (C) 1999-2012 The OpenNMS Group, Inc.
   *
   * OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc.
   *
   * OpenNMS(R) is free software: you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published
   * by the Free Software Foundation, either version 3 of the License,
   * or (at your option) any later version.
   *
   * OpenNMS(R) is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with OpenNMS(R).  If not, see:
   *      http://www.gnu.org/licenses/
   *
   * For more information contact:
   *     OpenNMS(R) Licensing <license@opennms.org>
   *     http://www.opennms.org/
   *     http://www.opennms.com/
   *******************************************************************************/
  
  package org.opennms.core.tasks;
  
  import static org.junit.Assert.assertArrayEquals;
  import static org.junit.Assert.assertEquals;
  import static org.junit.Assert.assertFalse;
  import static org.junit.Assert.assertTrue;
  
  import java.util.List;
  import java.util.Timer;
  import java.util.TimerTask;
  import java.util.Vector;
  import java.util.concurrent.CountDownLatch;
  import java.util.concurrent.ExecutorService;
  import java.util.concurrent.Executors;
  import java.util.concurrent.TimeUnit;
  import java.util.concurrent.atomic.AtomicBoolean;
  import java.util.concurrent.atomic.AtomicInteger;
  import java.util.concurrent.atomic.AtomicLong;
  
  import org.junit.Before;
  import org.junit.Test;
  import org.opennms.core.concurrent.LogPreservingThreadFactory;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  
  
  /**
   * BaseTaskTest
   *
   * @author brozow
   */
  public class TaskTest {
  	
  	private static final Logger LOG = LoggerFactory.getLogger(TaskTest.class);
      
      ExecutorService m_executor;
      DefaultTaskCoordinator m_coordinator;
      
      @Before
      public void setUp() {
          m_executor = Executors.newFixedThreadPool(50,
              new LogPreservingThreadFactory(getClass().getSimpleName(), 50, false)
          );
          m_coordinator = new DefaultTaskCoordinator("TaskTest", m_executor);
      }
      
      @Test
      public void testSimpleTask() throws Exception {
          final AtomicBoolean hasRun = new AtomicBoolean(false);
          
          Runnable r = new Runnable() {
              @Override
              public void run() {
                  sleep(100);
                  hasRun.set(true);
              }
          };
          
          Task task = createTask(r);
          
          task.schedule();
          
          assertFalse(hasRun.get());
          
          task.waitFor();
          
          assertTrue(hasRun.get());
          
      }
      
      @Test
      public void testTaskWithSingleDependency() throws Exception {
          
          final List<String> sequence = new Vector<String>();
          
          Task task1 = createTask(appender(sequence, "task1"));
          Task task2 = createTask(appender(sequence, "task2"));
          Task task3 = createTask(appender(sequence, "task3"));
  
          task2.addPrerequisite(task1);
          task3.addPrerequisite(task2);
  
          task3.schedule();
          
          task2.schedule();
          
          task1.schedule();
          
          task3.waitFor(3500, TimeUnit.MILLISECONDS);
          
          assertArrayEquals(new String[] { "task1", "task2", "task3" }, sequence.toArray(new String[0]));
          
      }
  
      private Task createTask(final Runnable runnable) {
          return m_coordinator.createTask(null, runnable);
      }
      
      @Test
      public void testTaskWithCompletedDependencies() throws Exception {
          
          
          final List<String> sequence = new Vector<String>();
          
          Task task1 = createTask(appender(sequence, "task1"));
          Task task2 = createTask(appender(sequence, "task2"));
          Task task3 = createTask(appender(sequence, "task3"));
  
          task1.schedule();
          
          task1.waitFor(10000, TimeUnit.MILLISECONDS);
  
          task2.addPrerequisite(task1);
          
          task2.schedule();
  
          task2.waitFor(10000, TimeUnit.MILLISECONDS);
          
          task3.addPrerequisite(task2);
  
          task3.schedule();
          
          
          task3.waitFor(3500, TimeUnit.MILLISECONDS);
          
          assertArrayEquals(new String[] { "task1", "task2", "task3" }, sequence.toArray(new String[0]));
          
      }
      
      @Test(timeout=1000)
      public void testTaskThatThrowsException() throws Exception {
          
          AtomicInteger count = new AtomicInteger(0);
      
          Runnable thrower = new Runnable() {
              @Override
              public void run() {
                  throw new RuntimeException("Intentionally failed for test purposes");
  
              }
          };
          
          Task throwerTask = m_coordinator.createTask(null, thrower);
          Task incrTask = m_coordinator.createTask(null, incr(count));
          
          incrTask.addPrerequisite(throwerTask);
          
          
          incrTask.schedule();
          throwerTask.schedule();
          
          
          incrTask.waitFor(1500, TimeUnit.MILLISECONDS);
  
          assertEquals(1, count.get());
      }
      
      @Test(timeout=1000)
      public void testAsyncThatThrowsException() throws Exception {
          
          AtomicInteger count = new AtomicInteger(0);
      
          Async<Integer> thrower = new Async<Integer>() {
  
              @Override
              public void submit(Callback<Integer> cb) {
                  throw new RuntimeException("Intentionally failed for test purposes");
              }
              
          };
             
          
          Task throwerTask = m_coordinator.createTask(null, thrower, setter(count));
          Task incrTask = m_coordinator.createTask(null, incr(count));
          
          incrTask.addPrerequisite(throwerTask);
          
          
          incrTask.schedule();
          throwerTask.schedule();
          
          
          incrTask.waitFor(1500, TimeUnit.MILLISECONDS);
  
          assertEquals(1, count.get());
      }
      
      @Test(timeout=1000)
      public void testAsync() throws Exception {
          final AtomicInteger count = new AtomicInteger(0);
          
          Task async = m_coordinator.createTask(null, timer(500, 17), setter(count));
          
          async.schedule();
          
          async.waitFor(15000, TimeUnit.MILLISECONDS);
          
          assertEquals(17, count.get());
      }
      
      @Test
      public void testBatchTask() throws Exception {
          
          AtomicInteger counter = new AtomicInteger(0);
          
          BatchTask batch = new BatchTask(m_coordinator, null);
  
          batch.add(incr(counter));
          batch.add(incr(counter));
          batch.add(incr(counter));
  
          batch.schedule();
          
          batch.waitFor(3500, TimeUnit.MILLISECONDS);
          
          assertEquals(3, counter.get());
          
      }
      
      @Test
      public void testSequenceTask() throws Exception {
          
  