package com.github.davidmoten.rx.internal.operators;
import static org.junit.Assert.assertEquals;
import static rx.Observable.from;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.TimeUnit;
import org.junit.Test;
import com.github.davidmoten.rx.Transformers;
import com.github.davidmoten.rx.testing.TestingHelper;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import rx.Observable;
import rx.Scheduler;
import rx.observers.TestSubscriber;
import rx.schedulers.Schedulers;
public class OrderedMergeTest {
private static final Comparator<Integer> comparator = new Comparator<Integer>() {
@Override
public int compare(Integer a, Integer b) {
return a.compareTo(b);
}
};
@Test
public void testMerge() {
// hang on to one stand-alone test like this so we can customize for
// failure cases arriving out of testWithAllCombinationsFromPowerSet
Observable<Integer> o1 = Observable.just(1, 2, 4, 10);
Observable<Integer> o2 = Observable.just(3, 5, 11);
check(o1, o2, 1, 2, 3, 4, 5, 10, 11);
}
@Test
public void testWithAllCombinationsFromPowerSet() {
checkAllCombinationsFromPowerSet(Schedulers.immediate());
}
@Test
public void testWithAllCombinationsFromPowerSetAsync() {
long t = System.currentTimeMillis();
while (System.currentTimeMillis() - t <= TimeUnit.SECONDS.toMillis(5)) {
checkAllCombinationsFromPowerSet(Schedulers.computation());
}
}
private void checkAllCombinationsFromPowerSet(Scheduler scheduler) {
// this test covers everything!
for (int n = 0; n <= 10; n++) {
Set<Integer> numbers = Sets.newTreeSet();
for (int i = 1; i <= n; i++) {
numbers.add(i);
}
for (Set<Integer> a : Sets.powerSet(numbers)) {
TreeSet<Integer> x = Sets.newTreeSet(a);
TreeSet<Integer> y = Sets.newTreeSet(Sets.difference(numbers, x));
Observable<Integer> o1 = from(x).subscribeOn(scheduler);
Observable<Integer> o2 = from(y).subscribeOn(scheduler);
List<Integer> list = o1.compose(Transformers.orderedMergeWith(o2, comparator)).toList().toBlocking()
.single();
// System.out.println(x + " " + y);
assertEquals(Lists.newArrayList(numbers), list);
}
}
}
private static void check(Observable<Integer> o1, Observable<Integer> o2, Integer... values) {
List<Integer> list = o1.compose(Transformers.orderedMergeWith(o2, comparator)).toList().toBlocking().single();
assertEquals(Arrays.asList(values), list);
}
@SuppressWarnings("unchecked")
@Test
public void testSymmetricMerge() {
Observable<Integer> o1 = Observable.just(1, 3, 5, 7);
Observable<Integer> o2 = Observable.just(2, 4, 6, 8);
TestSubscriber<Integer> ts = TestSubscriber.create();
OrderedMerge.create(Arrays.asList(o1, o2)).subscribe(ts);
ts.assertNoErrors();
ts.assertCompleted();
ts.assertValues(1, 2, 3, 4, 5, 6, 7, 8);
}
@SuppressWarnings("unchecked")
@Test
public void testAsymmetricMerge() {
Observable<Integer> o1 = Observable.just(1, 3, 5, 7);
Observable<Integer> o2 = Observable.just(2, 4);
TestSubscriber<Integer> ts = TestSubscriber.create();
OrderedMerge.create(Arrays.asList(o1, o2)).subscribe(ts);
ts.assertNoErrors();
ts.assertCompleted();
ts.assertValues(1, 2, 3, 4, 5, 7);
}
@SuppressWarnings("unchecked")
@Test
public void testSymmetricMergeAsync() {
Observable<Integer> o1 = Observable.just(1, 3, 5, 7).observeOn(Schedulers.computation());
Observable<Integer> o2 = Observable.just(2, 4, 6, 8).observeOn(Schedulers.computation());
OrderedMerge.<Integer> create(Arrays.asList(o1, o2)) //
.to(TestingHelper.<Integer>test())
.awaitTerminalEvent(1, TimeUnit.SECONDS) //
.assertNoErrors() //
.assertCompleted() //
.assertValues(1, 2, 3, 4, 5, 6, 7, 8);
}
@SuppressWarnings("unchecked")
@Test
public void testAsymmetricMergeAsync() {
Observable<Integer> o1 = Observable.just(1, 3, 5, 7).observeOn(Schedulers.computation());
Observable<Integer> o2 = Observable.just(2, 4).observeOn(Schedulers.computation());
TestSubscriber<Integer> ts = TestSubscriber.create();
OrderedMerge.create(Arrays.asList(o1, o2)).subscribe(ts);
ts.awaitTerminalEvent(1, TimeUnit.SECONDS);
ts.assertNoErrors();
ts.assertCompleted();
ts.assertValues(1, 2, 3, 4, 5, 7);
}
@SuppressWarnings("unchecked")
@Test
public void testEmptyEmpty() {
Observable<Integer> o1 = Observable.empty();
Observable<Integer> o2 = Observable.empty();
TestSubscriber<Integer> ts = TestSubscriber.create();
OrderedMerge.create(Arrays.asList(o1, o2)).subscribe(ts);
ts.assertNoErrors();
ts.assertCompleted();
ts.assertNoValues();
}
@SuppressWarnings("unchecked")
@Test
public void testEmptySomething1() {
Observable<Integer> o1 = Observable.just(1, 3, 5, 7);
Observable<Integer> o2 = Observable.empty();
TestSubscriber<Integer> ts = TestSubscriber.create();
OrderedMerge.create(Arrays.asList(o1, o2)).subscribe(ts);
ts.assertNoErrors();
ts.assertCompleted();
ts.assertValues(1, 3, 5, 7);
}
@SuppressWarnings("unchecked")
@Test
public void testEmptySomething2() {
Observable<Integer> o1 = Observable.just(1, 3, 5, 7);
Observable<Integer> o2 = Observable.empty();
TestSubscriber<Integer> ts = TestSubscriber.create();
OrderedMerge.create(Arrays.asList(o2, o1)).subscribe(ts);
ts.assertNoErrors();
ts.assertCompleted();
ts.assertValues(1, 3, 5, 7);
}
private static class TestException extends Exception {
private static final long serialVersionUID = -1204531902391807941L;
}
@SuppressWarnings("unchecked")
@Test
public void testErrorInMiddle() {
Observable<Integer> o1 = Observable.just(1, 3, 5, 7);
Observable<Integer> o2 = Observable.just(2).concatWith(Observable.<Integer> error(new TestException()));
TestSubscriber<Integer> ts = TestSubscriber.create();
OrderedMerge.create(Arrays.asList(o1, o2)).subscribe(ts);
ts.assertError(TestException.class);
ts.assertNotCompleted();
ts.assertValues(1, 2);
}
@SuppressWarnings("unchecked")
@Test
public void testErrorImmediately() {
Observable<Integer> o1 = Observable.just(1, 3, 5, 7);
Observable<Integer> o2 = Observable.<Integer> error(new TestException());
TestSubscriber<Integer> ts = TestSubscriber.create();
OrderedMerge.create(Arrays.asList(o1, o2)).subscribe(ts);
ts.assertError(TestException.class);
ts.assertNotCompleted();
ts.assertNoValues();
}
@SuppressWarnings("unchecked")
@Test
public void testErrorInMiddleDelayed() {
Observable<Integer> o1 = Observable.just(1, 3, 5, 7);
Observable<Integer> o2 = Observable.just(2).concatWith(Observable.<Integer> error(new TestException()));
TestSubscriber<Integer> ts = TestSubscriber.create();
OrderedMerge.create(Arrays.asList(o1, o2), true).subscribe(ts);
ts.assertError(TestException.class);
ts.assertValues(1, 2, 3, 5, 7);
ts.assertNotCompleted();
}
@SuppressWarnings("unchecked")
@Test
public void testErrorImmediatelyDelayed() {
Observable<Integer> o1 = Observable.just(1, 3, 5, 7);
Observable<Integer> o2 = Observable.<Integer> error(new TestException());
TestSubscriber<Integer> ts = TestSubscriber.create();
OrderedMerge.create(Arrays.asList(o1, o2), true).subscribe(ts);
ts.assertError(TestException.class);
ts.assertNotCompleted();
ts.assertValues(1, 3, 5, 7);
}
@SuppressWarnings("unchecked")
@Test
public void testTake() {
Observable<Integer> o1 = Observable.just(1, 3, 5, 7);
Observable<Integer> o2 = Observable.just(2, 4, 6, 8);
TestSubscriber<Integer> ts = TestSubscriber.create();
OrderedMerge.create(Arrays.asList(o1, o2)).take(2).subscribe(ts);
ts.assertNoErrors();
ts.assertCompleted();
ts.assertValues(1, 2);
}
@SuppressWarnings("unchecked")
@Test
public void testBackpressure() {
Observable<Integer> o1 = Observable.just(1, 3, 5, 7);
Observable<Integer> o2 = Observable.just(2, 4, 6, 8);
TestSubscriber<Integer> ts = TestSubscriber.create(0);
OrderedMerge.create(Arrays.asList(o1, o2)).subscribe(ts);
ts.requestMore(2);
ts.assertNoErrors();
ts.assertNotCompleted();
ts.assertValues(1, 2);
}
}