2011-03-01 15:23:29 -07:00
|
|
|
package akka.dispatch;
|
|
|
|
|
|
2011-12-14 17:30:54 +01:00
|
|
|
import akka.util.Timeout;
|
2011-11-10 20:08:00 +01:00
|
|
|
import akka.actor.ActorSystem;
|
2011-11-30 15:16:20 +01:00
|
|
|
|
2011-12-14 01:24:55 +01:00
|
|
|
import akka.japi.*;
|
2011-12-11 14:06:30 +01:00
|
|
|
import akka.util.Duration;
|
2011-11-30 15:16:20 +01:00
|
|
|
import org.junit.AfterClass;
|
|
|
|
|
import org.junit.BeforeClass;
|
2011-03-01 15:23:29 -07:00
|
|
|
import org.junit.Test;
|
|
|
|
|
import static org.junit.Assert.*;
|
|
|
|
|
import java.util.concurrent.Callable;
|
2011-04-15 13:09:53 -06:00
|
|
|
import java.util.LinkedList;
|
2011-05-11 13:29:29 +02:00
|
|
|
import java.lang.Iterable;
|
2011-08-12 17:23:34 +02:00
|
|
|
import java.util.concurrent.CountDownLatch;
|
|
|
|
|
import java.util.concurrent.TimeUnit;
|
2012-01-26 15:11:49 +01:00
|
|
|
import static akka.japi.util.manifest;
|
2011-08-12 17:23:34 +02:00
|
|
|
|
2011-11-30 15:16:20 +01:00
|
|
|
import akka.testkit.AkkaSpec;
|
2011-03-01 15:23:29 -07:00
|
|
|
|
2011-04-15 13:09:53 -06:00
|
|
|
public class JavaFutureTests {
|
2011-10-28 15:55:15 +02:00
|
|
|
|
2011-11-30 15:16:20 +01:00
|
|
|
private static ActorSystem system;
|
|
|
|
|
private static Timeout t;
|
2011-12-14 17:30:54 +01:00
|
|
|
|
2011-12-12 22:24:17 +01:00
|
|
|
private final Duration timeout = Duration.create(5, TimeUnit.SECONDS);
|
2011-11-30 15:16:20 +01:00
|
|
|
|
|
|
|
|
@BeforeClass
|
|
|
|
|
public static void beforeAll() {
|
|
|
|
|
system = ActorSystem.create("JavaFutureTests", AkkaSpec.testConf());
|
|
|
|
|
t = system.settings().ActorTimeout();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@AfterClass
|
|
|
|
|
public static void afterAll() {
|
2011-12-14 01:06:20 +01:00
|
|
|
system.shutdown();
|
2011-11-30 15:16:20 +01:00
|
|
|
system = null;
|
|
|
|
|
}
|
2011-11-15 11:34:39 +01:00
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
public void mustBeAbleToMapAFuture() {
|
2011-11-30 15:16:20 +01:00
|
|
|
|
2011-12-12 14:39:10 +01:00
|
|
|
Future<String> f1 = Futures.future(new Callable<String>() {
|
2011-11-15 11:34:39 +01:00
|
|
|
public String call() {
|
|
|
|
|
return "Hello";
|
|
|
|
|
}
|
2011-12-12 14:39:10 +01:00
|
|
|
}, system.dispatcher());
|
2011-11-15 11:34:39 +01:00
|
|
|
|
2012-01-26 14:15:25 +01:00
|
|
|
Future<String> f2 = f1.map(new Mapper<String, String>() {
|
2011-11-15 11:34:39 +01:00
|
|
|
public String apply(String s) {
|
|
|
|
|
return s + " World";
|
|
|
|
|
}
|
2011-12-11 00:40:52 +01:00
|
|
|
});
|
2011-11-15 11:34:39 +01:00
|
|
|
|
2011-12-12 22:50:08 +01:00
|
|
|
assertEquals("Hello World", Await.result(f2, timeout));
|
2011-11-15 11:34:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
public void mustBeAbleToExecuteAnOnResultCallback() throws Throwable {
|
|
|
|
|
final CountDownLatch latch = new CountDownLatch(1);
|
2011-12-12 14:39:10 +01:00
|
|
|
Promise<String> cf = Futures.promise(system.dispatcher());
|
2011-11-15 11:34:39 +01:00
|
|
|
Future<String> f = cf;
|
2012-01-26 14:15:25 +01:00
|
|
|
f.onSuccess(new OnSuccess<String>() {
|
|
|
|
|
public void onSuccess(String result) {
|
2011-12-12 22:24:17 +01:00
|
|
|
if (result.equals("foo"))
|
|
|
|
|
latch.countDown();
|
|
|
|
|
}
|
2011-11-15 11:34:39 +01:00
|
|
|
});
|
|
|
|
|
|
2011-12-12 17:25:34 +01:00
|
|
|
cf.success("foo");
|
2011-11-15 11:34:39 +01:00
|
|
|
assertTrue(latch.await(5000, TimeUnit.MILLISECONDS));
|
2011-12-12 22:50:08 +01:00
|
|
|
assertEquals(Await.result(f, timeout), "foo");
|
2011-11-15 11:34:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
public void mustBeAbleToExecuteAnOnExceptionCallback() throws Throwable {
|
|
|
|
|
final CountDownLatch latch = new CountDownLatch(1);
|
2011-12-12 14:39:10 +01:00
|
|
|
Promise<String> cf = Futures.promise(system.dispatcher());
|
2011-11-15 11:34:39 +01:00
|
|
|
Future<String> f = cf;
|
2012-01-26 14:15:25 +01:00
|
|
|
f.onFailure(new OnFailure() {
|
|
|
|
|
public void onFailure(Throwable t) {
|
2011-12-12 22:24:17 +01:00
|
|
|
if (t instanceof NullPointerException)
|
|
|
|
|
latch.countDown();
|
|
|
|
|
}
|
2011-11-15 11:34:39 +01:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
Throwable exception = new NullPointerException();
|
2011-12-12 17:25:34 +01:00
|
|
|
cf.failure(exception);
|
2011-11-15 11:34:39 +01:00
|
|
|
assertTrue(latch.await(5000, TimeUnit.MILLISECONDS));
|
2011-12-12 12:41:56 +01:00
|
|
|
assertEquals(f.value().get().left().get(), exception);
|
2011-11-15 11:34:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
public void mustBeAbleToExecuteAnOnCompleteCallback() throws Throwable {
|
|
|
|
|
final CountDownLatch latch = new CountDownLatch(1);
|
2011-12-12 14:39:10 +01:00
|
|
|
Promise<String> cf = Futures.promise(system.dispatcher());
|
2011-11-15 11:34:39 +01:00
|
|
|
Future<String> f = cf;
|
2012-01-26 14:15:25 +01:00
|
|
|
f.onComplete(new OnComplete<String>() {
|
|
|
|
|
public void onComplete(Throwable t, String r) {
|
2011-11-15 11:34:39 +01:00
|
|
|
latch.countDown();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2011-12-12 17:25:34 +01:00
|
|
|
cf.success("foo");
|
2011-11-15 11:34:39 +01:00
|
|
|
assertTrue(latch.await(5000, TimeUnit.MILLISECONDS));
|
2011-12-12 22:50:08 +01:00
|
|
|
assertEquals(Await.result(f, timeout), "foo");
|
2011-11-15 11:34:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
public void mustBeAbleToForeachAFuture() throws Throwable {
|
|
|
|
|
final CountDownLatch latch = new CountDownLatch(1);
|
2011-12-12 14:39:10 +01:00
|
|
|
Promise<String> cf = Futures.promise(system.dispatcher());
|
2011-11-15 11:34:39 +01:00
|
|
|
Future<String> f = cf;
|
2012-01-26 14:15:25 +01:00
|
|
|
f.foreach(new Foreach<String>() {
|
|
|
|
|
public void each(String future) {
|
2011-11-15 11:34:39 +01:00
|
|
|
latch.countDown();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2011-12-12 17:25:34 +01:00
|
|
|
cf.success("foo");
|
2011-11-15 11:34:39 +01:00
|
|
|
assertTrue(latch.await(5000, TimeUnit.MILLISECONDS));
|
2011-12-12 22:50:08 +01:00
|
|
|
assertEquals(Await.result(f, timeout), "foo");
|
2011-11-15 11:34:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
public void mustBeAbleToFlatMapAFuture() throws Throwable {
|
|
|
|
|
final CountDownLatch latch = new CountDownLatch(1);
|
2011-12-12 14:39:10 +01:00
|
|
|
Promise<String> cf = Futures.promise(system.dispatcher());
|
2011-12-12 17:25:34 +01:00
|
|
|
cf.success("1000");
|
2011-11-15 11:34:39 +01:00
|
|
|
Future<String> f = cf;
|
2012-01-26 14:15:25 +01:00
|
|
|
Future<Integer> r = f.flatMap(new Mapper<String, Future<Integer>>() {
|
2011-11-15 11:34:39 +01:00
|
|
|
public Future<Integer> apply(String r) {
|
|
|
|
|
latch.countDown();
|
2011-12-12 14:39:10 +01:00
|
|
|
Promise<Integer> cf = Futures.promise(system.dispatcher());
|
2011-12-12 17:25:34 +01:00
|
|
|
cf.success(Integer.parseInt(r));
|
2011-11-15 11:34:39 +01:00
|
|
|
return cf;
|
|
|
|
|
}
|
2011-12-11 00:40:52 +01:00
|
|
|
});
|
2011-11-15 11:34:39 +01:00
|
|
|
|
2011-12-12 22:50:08 +01:00
|
|
|
assertEquals(Await.result(f, timeout), "1000");
|
|
|
|
|
assertEquals(Await.result(r, timeout).intValue(), 1000);
|
2011-11-15 11:34:39 +01:00
|
|
|
assertTrue(latch.await(5000, TimeUnit.MILLISECONDS));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
public void mustBeAbleToFilterAFuture() throws Throwable {
|
|
|
|
|
final CountDownLatch latch = new CountDownLatch(1);
|
2011-12-12 14:39:10 +01:00
|
|
|
Promise<String> cf = Futures.promise(system.dispatcher());
|
2011-11-15 11:34:39 +01:00
|
|
|
Future<String> f = cf;
|
2012-01-26 14:15:25 +01:00
|
|
|
Future<String> r = f.filter(new Filter<String>() {
|
|
|
|
|
public boolean filter(String r) {
|
2011-11-15 11:34:39 +01:00
|
|
|
latch.countDown();
|
|
|
|
|
return r.equals("foo");
|
|
|
|
|
}
|
2011-12-11 00:40:52 +01:00
|
|
|
});
|
2011-11-15 11:34:39 +01:00
|
|
|
|
2011-12-12 17:25:34 +01:00
|
|
|
cf.success("foo");
|
2011-11-15 11:34:39 +01:00
|
|
|
assertTrue(latch.await(5000, TimeUnit.MILLISECONDS));
|
2011-12-12 22:50:08 +01:00
|
|
|
assertEquals(Await.result(f, timeout), "foo");
|
|
|
|
|
assertEquals(Await.result(r, timeout), "foo");
|
2011-11-15 11:34:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO: Improve this test, perhaps with an Actor
|
|
|
|
|
@Test
|
|
|
|
|
public void mustSequenceAFutureList() {
|
|
|
|
|
LinkedList<Future<String>> listFutures = new LinkedList<Future<String>>();
|
|
|
|
|
LinkedList<String> listExpected = new LinkedList<String>();
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < 10; i++) {
|
|
|
|
|
listExpected.add("test");
|
2011-12-12 14:39:10 +01:00
|
|
|
listFutures.add(Futures.future(new Callable<String>() {
|
2011-11-15 11:34:39 +01:00
|
|
|
public String call() {
|
|
|
|
|
return "test";
|
|
|
|
|
}
|
2011-12-12 14:39:10 +01:00
|
|
|
}, system.dispatcher()));
|
2011-08-12 17:23:34 +02:00
|
|
|
}
|
|
|
|
|
|
2011-12-12 14:39:10 +01:00
|
|
|
Future<Iterable<String>> futureList = Futures.sequence(listFutures, system.dispatcher());
|
2011-08-12 17:23:34 +02:00
|
|
|
|
2011-12-12 22:50:08 +01:00
|
|
|
assertEquals(Await.result(futureList, timeout), listExpected);
|
2011-11-15 11:34:39 +01:00
|
|
|
}
|
2011-08-12 17:23:34 +02:00
|
|
|
|
2011-11-15 11:34:39 +01:00
|
|
|
// TODO: Improve this test, perhaps with an Actor
|
|
|
|
|
@Test
|
|
|
|
|
public void foldForJavaApiMustWork() {
|
|
|
|
|
LinkedList<Future<String>> listFutures = new LinkedList<Future<String>>();
|
|
|
|
|
StringBuilder expected = new StringBuilder();
|
2011-08-12 17:23:34 +02:00
|
|
|
|
2011-11-15 11:34:39 +01:00
|
|
|
for (int i = 0; i < 10; i++) {
|
|
|
|
|
expected.append("test");
|
2011-12-12 14:39:10 +01:00
|
|
|
listFutures.add(Futures.future(new Callable<String>() {
|
2011-11-15 11:34:39 +01:00
|
|
|
public String call() {
|
|
|
|
|
return "test";
|
2011-04-15 13:09:53 -06:00
|
|
|
}
|
2011-12-12 14:39:10 +01:00
|
|
|
}, system.dispatcher()));
|
2011-03-01 15:23:29 -07:00
|
|
|
}
|
|
|
|
|
|
2011-12-12 14:39:10 +01:00
|
|
|
Future<String> result = Futures.fold("", listFutures, new Function2<String, String, String>() {
|
2011-11-15 11:34:39 +01:00
|
|
|
public String apply(String r, String t) {
|
|
|
|
|
return r + t;
|
|
|
|
|
}
|
2011-12-12 14:39:10 +01:00
|
|
|
}, system.dispatcher());
|
2011-11-15 11:34:39 +01:00
|
|
|
|
2011-12-12 22:50:08 +01:00
|
|
|
assertEquals(Await.result(result, timeout), expected.toString());
|
2011-11-15 11:34:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
public void reduceForJavaApiMustWork() {
|
|
|
|
|
LinkedList<Future<String>> listFutures = new LinkedList<Future<String>>();
|
|
|
|
|
StringBuilder expected = new StringBuilder();
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < 10; i++) {
|
|
|
|
|
expected.append("test");
|
2011-12-12 14:39:10 +01:00
|
|
|
listFutures.add(Futures.future(new Callable<String>() {
|
2011-11-15 11:34:39 +01:00
|
|
|
public String call() {
|
|
|
|
|
return "test";
|
2011-05-10 19:19:13 +02:00
|
|
|
}
|
2011-12-12 14:39:10 +01:00
|
|
|
}, system.dispatcher()));
|
2011-05-10 19:19:13 +02:00
|
|
|
}
|
|
|
|
|
|
2011-12-12 14:39:10 +01:00
|
|
|
Future<String> result = Futures.reduce(listFutures, new Function2<String, String, String>() {
|
2011-11-15 11:34:39 +01:00
|
|
|
public String apply(String r, String t) {
|
|
|
|
|
return r + t;
|
|
|
|
|
}
|
2011-12-12 14:39:10 +01:00
|
|
|
}, system.dispatcher());
|
2011-05-10 19:19:13 +02:00
|
|
|
|
2011-12-12 22:50:08 +01:00
|
|
|
assertEquals(Await.result(result, timeout), expected.toString());
|
2011-11-15 11:34:39 +01:00
|
|
|
}
|
2011-05-10 19:19:13 +02:00
|
|
|
|
2011-11-15 11:34:39 +01:00
|
|
|
@Test
|
|
|
|
|
public void traverseForJavaApiMustWork() {
|
|
|
|
|
LinkedList<String> listStrings = new LinkedList<String>();
|
|
|
|
|
LinkedList<String> expectedStrings = new LinkedList<String>();
|
2011-05-10 19:19:13 +02:00
|
|
|
|
2011-11-15 11:34:39 +01:00
|
|
|
for (int i = 0; i < 10; i++) {
|
|
|
|
|
expectedStrings.add("TEST");
|
|
|
|
|
listStrings.add("test");
|
|
|
|
|
}
|
2011-05-10 19:19:13 +02:00
|
|
|
|
2011-12-12 14:39:10 +01:00
|
|
|
Future<Iterable<String>> result = Futures.traverse(listStrings, new Function<String, Future<String>>() {
|
2011-11-15 11:34:39 +01:00
|
|
|
public Future<String> apply(final String r) {
|
2011-12-12 14:39:10 +01:00
|
|
|
return Futures.future(new Callable<String>() {
|
2011-11-15 11:34:39 +01:00
|
|
|
public String call() {
|
|
|
|
|
return r.toUpperCase();
|
2011-05-10 19:19:13 +02:00
|
|
|
}
|
2011-12-12 14:39:10 +01:00
|
|
|
}, system.dispatcher());
|
2011-11-15 11:34:39 +01:00
|
|
|
}
|
2011-12-12 14:39:10 +01:00
|
|
|
}, system.dispatcher());
|
2011-11-15 11:34:39 +01:00
|
|
|
|
2011-12-12 22:50:08 +01:00
|
|
|
assertEquals(Await.result(result, timeout), expectedStrings);
|
2011-11-15 11:34:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
public void findForJavaApiMustWork() {
|
|
|
|
|
LinkedList<Future<Integer>> listFutures = new LinkedList<Future<Integer>>();
|
|
|
|
|
for (int i = 0; i < 10; i++) {
|
|
|
|
|
final Integer fi = i;
|
2011-12-12 14:39:10 +01:00
|
|
|
listFutures.add(Futures.future(new Callable<Integer>() {
|
2011-11-15 11:34:39 +01:00
|
|
|
public Integer call() {
|
|
|
|
|
return fi;
|
2011-08-26 17:25:18 +02:00
|
|
|
}
|
2011-12-12 14:39:10 +01:00
|
|
|
}, system.dispatcher()));
|
2011-08-26 17:25:18 +02:00
|
|
|
}
|
2011-11-15 11:34:39 +01:00
|
|
|
final Integer expect = 5;
|
2011-12-12 14:39:10 +01:00
|
|
|
Future<Option<Integer>> f = Futures.find(listFutures, new Function<Integer, Boolean>() {
|
2011-11-15 11:34:39 +01:00
|
|
|
public Boolean apply(Integer i) {
|
|
|
|
|
return i == 5;
|
|
|
|
|
}
|
2011-12-12 14:39:10 +01:00
|
|
|
}, system.dispatcher());
|
2011-11-15 11:34:39 +01:00
|
|
|
|
2011-12-12 22:50:08 +01:00
|
|
|
assertEquals(expect, Await.result(f, timeout));
|
2011-12-11 14:06:30 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
public void BlockMustBeCallable() {
|
2011-12-12 14:39:10 +01:00
|
|
|
Promise<String> p = Futures.promise(system.dispatcher());
|
2011-12-11 14:06:30 +01:00
|
|
|
Duration d = Duration.create(1, TimeUnit.SECONDS);
|
2011-12-12 17:25:34 +01:00
|
|
|
p.success("foo");
|
2011-12-12 22:50:08 +01:00
|
|
|
Await.ready(p, d);
|
|
|
|
|
assertEquals(Await.result(p, d), "foo");
|
2011-11-15 11:34:39 +01:00
|
|
|
}
|
2012-01-26 15:11:49 +01:00
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
public void MapToMustBeCallable() {
|
|
|
|
|
Promise<Object> p = Futures.promise(system.dispatcher());
|
|
|
|
|
Future<String> f = p.future().mapTo(manifest(String.class));
|
|
|
|
|
Duration d = Duration.create(1, TimeUnit.SECONDS);
|
|
|
|
|
p.success("foo");
|
|
|
|
|
Await.ready(p, d);
|
|
|
|
|
assertEquals(Await.result(p, d), "foo");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
public void RecoverToMustBeCallable() {
|
|
|
|
|
final IllegalStateException fail = new IllegalStateException("OHNOES");
|
|
|
|
|
Promise<Object> p = Futures.promise(system.dispatcher());
|
|
|
|
|
Future<Object> f = p.future().recover(new Recover<Object>() {
|
|
|
|
|
public Object recover(Throwable t) throws Throwable {
|
|
|
|
|
if (t == fail) return "foo";
|
|
|
|
|
else throw t;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
Duration d = Duration.create(1, TimeUnit.SECONDS);
|
|
|
|
|
p.failure(fail);
|
|
|
|
|
Await.ready(p, d);
|
|
|
|
|
assertEquals(Await.result(p, d), "foo");
|
|
|
|
|
}
|
2011-03-01 15:23:29 -07:00
|
|
|
}
|