1   package com.atlassian.util.concurrent;
2   
3   import static com.atlassian.util.concurrent.Util.pause;
4   import static org.junit.Assert.assertEquals;
5   import static org.junit.Assert.assertFalse;
6   import static org.junit.Assert.assertTrue;
7   import static org.junit.Assert.fail;
8   
9   import org.junit.Test;
10  
11  import java.util.concurrent.CountDownLatch;
12  import java.util.concurrent.atomic.AtomicInteger;
13  
14  public class SettableFutureTest {
15      @Test public void isDoneOnceSet() throws InterruptedException {
16          final SettableFuture<Integer> future = new SettableFuture<Integer>();
17          assertFalse(future.isDone());
18          future.set(1);
19          assertTrue(future.isDone());
20          assertEquals(Integer.valueOf(1), future.get());
21      }
22  
23      @Test public void onlySettableOnce() throws InterruptedException {
24          final SettableFuture<Integer> future = new SettableFuture<Integer>();
25          future.set(1);
26          try {
27              future.set(2);
28              fail("should not be settable twice with different value");
29          }
30          catch (final IllegalArgumentException expected) {}
31          assertEquals(Integer.valueOf(1), future.get());
32      }
33  
34      @Test public void onlySettableOnceWithNull() throws InterruptedException {
35          final SettableFuture<Integer> future = new SettableFuture<Integer>();
36          future.set(null);
37          try {
38              future.set(2);
39              fail("should not be settable twice with different value");
40          }
41          catch (final IllegalArgumentException expected) {}
42          assertEquals(null, future.get());
43      }
44  
45      @Test public void settableTwiceWithSameValue() throws InterruptedException {
46          final SettableFuture<Integer> future = new SettableFuture<Integer>();
47          future.set(1);
48          future.set(1);
49          assertEquals(Integer.valueOf(1), future.get());
50      }
51  
52      @Test public void settableTwiceWithNullValue() throws InterruptedException {
53          final SettableFuture<Integer> future = new SettableFuture<Integer>();
54          future.set(1);
55          future.set(1);
56          assertEquals(Integer.valueOf(1), future.get());
57      }
58  
59      @Test public void notCancellable() {
60          final SettableFuture<Integer> future = new SettableFuture<Integer>();
61          future.cancel(false);
62          assertEquals(false, future.isCancelled());
63          future.cancel(true);
64          assertEquals(false, future.isCancelled());
65      }
66  
67      @Test public void getWaits() throws InterruptedException {
68          final SettableFuture<Integer> future = new SettableFuture<Integer>();
69          final CountDownLatch running = new CountDownLatch(1);
70          final AtomicInteger count = new AtomicInteger(3);
71          final CountDownLatch complete = new CountDownLatch(1);
72          new Thread(new Runnable() {
73              public void run() {
74                  try {
75                      running.countDown();
76                      count.set(future.get());
77                      complete.countDown();
78                  }
79                  catch (final InterruptedException e) {
80                      throw new RuntimeInterruptedException(e);
81                  }
82              }
83          }).start();
84          running.await();
85          pause();
86          assertFalse(future.isDone());
87          assertEquals(3, count.get());
88          future.set(12);
89          complete.await();
90          assertEquals(12, count.get());
91          assertTrue(future.isDone());
92      }
93  }