Home | History | Annotate | Download | only in concurrent
      1 /*
      2  * Copyright (C) 2007 The Guava Authors
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  * http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.google.common.util.concurrent;
     18 
     19 import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
     20 
     21 import com.google.common.testing.NullPointerTester;
     22 
     23 import junit.framework.TestCase;
     24 
     25 import java.util.concurrent.CountDownLatch;
     26 import java.util.concurrent.Executor;
     27 import java.util.concurrent.Executors;
     28 import java.util.concurrent.TimeUnit;
     29 import java.util.concurrent.atomic.AtomicInteger;
     30 
     31 /**
     32  * Unit tests for {@link ExecutionList}.
     33  *
     34  * @author Nishant Thakkar
     35  * @author Sven Mawson
     36  */
     37 public class ExecutionListTest extends TestCase {
     38 
     39   private final ExecutionList list = new ExecutionList();
     40 
     41   public void testRunOnPopulatedList() throws Exception {
     42     Executor exec = Executors.newCachedThreadPool();
     43     CountDownLatch countDownLatch = new CountDownLatch(3);
     44     list.add(new MockRunnable(countDownLatch), exec);
     45     list.add(new MockRunnable(countDownLatch), exec);
     46     list.add(new MockRunnable(countDownLatch), exec);
     47     assertEquals(countDownLatch.getCount(), 3L);
     48 
     49     list.execute();
     50 
     51     // Verify that all of the runnables execute in a reasonable amount of time.
     52     assertTrue(countDownLatch.await(1L, TimeUnit.SECONDS));
     53   }
     54 
     55   public void testExecute_idempotent() {
     56     final AtomicInteger runCalled = new AtomicInteger();
     57     list.add(new Runnable() {
     58       @Override public void run() {
     59         runCalled.getAndIncrement();
     60       }
     61     }, directExecutor());
     62     list.execute();
     63     assertEquals(1, runCalled.get());
     64     list.execute();
     65     assertEquals(1, runCalled.get());
     66   }
     67 
     68   public void testExecute_idempotentConcurrently() throws InterruptedException {
     69     final CountDownLatch okayToRun = new CountDownLatch(1);
     70     final AtomicInteger runCalled = new AtomicInteger();
     71     list.add(new Runnable() {
     72       @Override public void run() {
     73         try {
     74           okayToRun.await();
     75         } catch (InterruptedException e) {
     76           Thread.currentThread().interrupt();
     77           throw new RuntimeException(e);
     78         }
     79         runCalled.getAndIncrement();
     80       }
     81     }, directExecutor());
     82     Runnable execute = new Runnable() {
     83       @Override public void run() {
     84         list.execute();
     85       }
     86     };
     87     Thread thread1 = new Thread(execute);
     88     Thread thread2 = new Thread(execute);
     89     thread1.start();
     90     thread2.start();
     91     assertEquals(0, runCalled.get());
     92     okayToRun.countDown();
     93     thread1.join();
     94     thread2.join();
     95     assertEquals(1, runCalled.get());
     96   }
     97 
     98   public void testAddAfterRun() throws Exception {
     99     // Run the previous test
    100     testRunOnPopulatedList();
    101 
    102     // If it passed, then verify an Add will be executed without calling run
    103     CountDownLatch countDownLatch = new CountDownLatch(1);
    104     list.add(new MockRunnable(countDownLatch),  Executors.newCachedThreadPool());
    105     assertTrue(countDownLatch.await(1L, TimeUnit.SECONDS));
    106   }
    107 
    108   public void testOrdering() throws Exception {
    109     final AtomicInteger integer = new AtomicInteger();
    110     for (int i = 0; i < 10; i++) {
    111       final int expectedCount = i;
    112       list.add(
    113           new Runnable() {
    114             @Override public void run() {
    115               integer.compareAndSet(expectedCount, expectedCount + 1);
    116             }
    117           },
    118           MoreExecutors.directExecutor());
    119     }
    120     list.execute();
    121     assertEquals(10, integer.get());
    122   }
    123 
    124   private class MockRunnable implements Runnable {
    125     CountDownLatch countDownLatch;
    126 
    127     MockRunnable(CountDownLatch countDownLatch) {
    128       this.countDownLatch = countDownLatch;
    129     }
    130 
    131     @Override public void run() {
    132       countDownLatch.countDown();
    133     }
    134   }
    135 
    136   public void testExceptionsCaught() {
    137     list.add(THROWING_RUNNABLE, directExecutor());
    138     list.execute();
    139     list.add(THROWING_RUNNABLE, directExecutor());
    140   }
    141 
    142   public void testNulls() {
    143     new NullPointerTester().testAllPublicInstanceMethods(new ExecutionList());
    144   }
    145 
    146   private static final Runnable THROWING_RUNNABLE = new Runnable() {
    147     @Override public void run() {
    148       throw new RuntimeException();
    149     }
    150   };
    151 }
    152