/**
* Copyright 2014 Netflix, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package rx.internal.operators;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static rx.internal.operators.BlockingOperatorToFuture.toFuture;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import org.junit.Test;
import rx.Observable;
import rx.Observable.OnSubscribe;
import rx.Subscriber;
import rx.exceptions.TestException;
public class BlockingOperatorToFutureTest {
@Test
public void testToFuture() throws InterruptedException, ExecutionException {
Observable<String> obs = Observable.just("one");
Future<String> f = toFuture(obs);
assertEquals("one", f.get());
}
@Test
public void testToFutureList() throws InterruptedException, ExecutionException {
Observable<String> obs = Observable.just("one", "two", "three");
Future<List<String>> f = toFuture(obs.toList());
assertEquals("one", f.get().get(0));
assertEquals("two", f.get().get(1));
assertEquals("three", f.get().get(2));
}
@Test(expected = IllegalArgumentException.class)
public void testExceptionWithMoreThanOneElement() throws Throwable {
Observable<String> obs = Observable.just("one", "two");
Future<String> f = toFuture(obs);
try {
// we expect an exception since there are more than 1 element
f.get();
}
catch(ExecutionException e) {
throw e.getCause();
}
}
@Test
public void testToFutureWithException() {
Observable<String> obs = Observable.create(new OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> observer) {
observer.onNext("one");
observer.onError(new TestException());
}
});
Future<String> f = toFuture(obs);
try {
f.get();
fail("expected exception");
} catch (Throwable e) {
assertEquals(TestException.class, e.getCause().getClass());
}
}
@Test(expected=CancellationException.class)
public void testGetAfterCancel() throws Exception {
Observable<String> obs = Observable.create(new OperationNeverComplete<String>());
Future<String> f = toFuture(obs);
boolean cancelled = f.cancel(true);
assertTrue(cancelled); // because OperationNeverComplete never does
f.get(); // Future.get() docs require this to throw
}
@Test(expected=CancellationException.class)
public void testGetWithTimeoutAfterCancel() throws Exception {
Observable<String> obs = Observable.create(new OperationNeverComplete<String>());
Future<String> f = toFuture(obs);
boolean cancelled = f.cancel(true);
assertTrue(cancelled); // because OperationNeverComplete never does
f.get(Long.MAX_VALUE, TimeUnit.NANOSECONDS); // Future.get() docs require this to throw
}
/**
* Emits no observations. Used to simulate a long-running asynchronous operation.
*/
private static class OperationNeverComplete<T> implements Observable.OnSubscribe<T> {
@Override
public void call(Subscriber<? super T> unused) {
// do nothing
}
}
@Test(expected = NoSuchElementException.class)
public void testGetWithEmptyObservable() throws Throwable {
Observable<String> obs = Observable.empty();
Future<String> f = obs.toBlocking().toFuture();
try {
f.get();
}
catch(ExecutionException e) {
throw e.getCause();
}
}
@Test
public void testGetWithASingleNullItem() throws Exception {
Observable<String> obs = Observable.just((String)null);
Future<String> f = obs.toBlocking().toFuture();
assertEquals(null, f.get());
}
}