package com.github.davidmoten.rx;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runners.MethodSorters;
import com.github.davidmoten.rx.util.Pair;
import rx.Observable;
import rx.Observable.Transformer;
import rx.Subscription;
import rx.functions.Func1;
import rx.functions.Func2;
import rx.observers.TestSubscriber;
import rx.schedulers.TestScheduler;
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TransformersTest {
@Test
public void testStatisticsOnEmptyStream() {
Observable<Integer> nums = Observable.empty();
Statistics s = nums.compose(Transformers.collectStats()).last().toBlocking().single();
assertEquals(0, s.count());
assertEquals(0, s.sum(), 0.0001);
assertTrue(Double.isNaN(s.mean()));
assertTrue(Double.isNaN(s.sd()));
}
@Test
public void testStatisticsOnSingleElement() {
Observable<Integer> nums = Observable.just(1);
Statistics s = nums.compose(Transformers.collectStats()).last().toBlocking().single();
assertEquals(1, s.count());
assertEquals(1, s.sum(), 0.0001);
assertEquals(1.0, s.mean(), 0.00001);
assertEquals(0, s.sd(), 0.00001);
}
@Test
public void testStatisticsOnMultipleElements() {
Observable<Integer> nums = Observable.just(1, 4, 10, 20);
Statistics s = nums.compose(Transformers.collectStats()).last().toBlocking().single();
assertEquals(4, s.count());
assertEquals(35.0, s.sum(), 0.0001);
assertEquals(8.75, s.mean(), 0.00001);
assertEquals(7.258615570478987, s.sd(), 0.00001);
}
@Test
public void testStatisticsPairOnEmptyStream() {
Observable<Integer> nums = Observable.empty();
boolean isEmpty = nums.compose(Transformers.collectStats(Functions.<Integer> identity()))
.isEmpty().toBlocking().single();
assertTrue(isEmpty);
}
@Test
public void testStatisticsPairOnSingleElement() {
Observable<Integer> nums = Observable.just(1);
Pair<Integer, Statistics> s = nums
.compose(Transformers.collectStats(Functions.<Integer> identity())).last()
.toBlocking().single();
assertEquals(1, (int) s.a());
assertEquals(1, s.b().count());
assertEquals(1, s.b().sum(), 0.0001);
assertEquals(1.0, s.b().mean(), 0.00001);
assertEquals(0, s.b().sd(), 0.00001);
}
@Test
public void testStatisticsPairOnMultipleElements() {
Observable<Integer> nums = Observable.just(1, 4, 10, 20);
Pair<Integer, Statistics> s = nums
.compose(Transformers.collectStats(Functions.<Integer> identity())).last()
.toBlocking().single();
assertEquals(4, s.b().count());
assertEquals(35.0, s.b().sum(), 0.0001);
assertEquals(8.75, s.b().mean(), 0.00001);
assertEquals(7.258615570478987, s.b().sd(), 0.00001);
}
@Test
public void testSort() {
Observable<Integer> o = Observable.just(5, 3, 1, 4, 2);
List<Integer> list = o.compose(Transformers.<Integer> sort()).toList().toBlocking()
.single();
assertEquals(Arrays.asList(1, 2, 3, 4, 5), list);
}
@Test
public void testSortWithComparator() {
Observable<Integer> o = Observable.just(5, 3, 1, 4, 2);
List<Integer> list = o.compose(Transformers.<Integer> sort(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2.compareTo(o1);
}
})).toList().toBlocking().single();
assertEquals(Arrays.asList(5, 4, 3, 2, 1), list);
}
@Test
public void testDoOnNth() {
AtomicInteger item = new AtomicInteger();
Observable.just(1, 2, 3).compose(Transformers.doOnNext(2, Actions.setAtomic(item)))
.subscribe();
assertEquals(2, item.get());
}
@Test
public void testDelay() {
final AtomicInteger count = new AtomicInteger();
Observable<Long> o = Observable //
.<Long> never() //
.doOnSubscribe(Actions.increment0(count)) //
.share();
Subscription s1 = o.subscribe();
assertEquals(1, count.get());
Subscription s2 = o.subscribe();
assertEquals(1, count.get());
s1.unsubscribe();
s2.unsubscribe();
o.subscribe();
assertEquals(2, count.get());
}
@Test
// @org.junit.Ignore
public void testDelayFinalUnsubscribeForRefCount() {
TestScheduler s = new TestScheduler();
final AtomicInteger count = new AtomicInteger();
Observable<Long> o = Observable //
.interval(1, TimeUnit.SECONDS, s) //
.doOnSubscribe(Actions.increment0(count)) //
.publish() //
.refCount() //
.compose(Transformers.<Long> delayFinalUnsubscribe(2500, TimeUnit.MILLISECONDS, s));
{
TestSubscriber<Long> ts1 = TestSubscriber.create();
o.subscribe(ts1);
assertEquals(1, count.get());
s.advanceTimeBy(1, TimeUnit.SECONDS);
ts1.assertValues(0L);
ts1.unsubscribe();
}
s.advanceTimeBy(1, TimeUnit.SECONDS);
{
TestSubscriber<Long> ts2 = TestSubscriber.create();
o.subscribe(ts2);
ts2.assertNoValues();
s.advanceTimeBy(1, TimeUnit.SECONDS);
ts2.assertValues(2L);
ts2.unsubscribe();
}
assertEquals(1, count.get());
s.advanceTimeBy(2500, TimeUnit.MILLISECONDS);
{
TestSubscriber<Long> ts3 = TestSubscriber.create();
s.advanceTimeBy(1, TimeUnit.SECONDS);
o.subscribe(ts3);
assertEquals(2, count.get());
s.advanceTimeBy(1, TimeUnit.SECONDS);
ts3.assertValues(0L);
}
}
@Test
public void testRemovePairsLeavesEmpty() {
List<Integer> list = Observable.just(1, 2).compose(removePairs()).toList().toBlocking()
.single();
assertTrue(list.isEmpty());
}
@Test
public void testRemovePairsFromRepeatedLeavesEmpty() {
List<Integer> list = Observable.just(1, 2, 1, 2).compose(removePairs()).toList()
.toBlocking().single();
assertTrue(list.isEmpty());
}
@Test
public void testRemovePairsFromRepeatedLeavesLast() {
List<Integer> list = Observable.just(1, 2, 1, 2, 3).compose(removePairs()).toList()
.toBlocking().single();
assertEquals(Arrays.asList(3), list);
}
@Test
public void testRemovePairsFromRepeatedLeavesFirst() {
List<Integer> list = Observable.just(3, 1, 2, 1, 2).compose(removePairs()).toList()
.toBlocking().single();
assertEquals(Arrays.asList(3), list);
}
@Test
public void testRemovePairsFromRepeatedLeavesMiddle() {
List<Integer> list = Observable.just(1, 2, 3, 1, 2).compose(removePairs()).toList()
.toBlocking().single();
assertEquals(Arrays.asList(3), list);
}
@Test
public void testRemovePairsFromEmpty() {
List<Integer> list = Observable.<Integer> empty().compose(removePairs()).toList()
.toBlocking().single();
assertTrue(list.isEmpty());
}
@Test
public void testRemovePairs1() {
List<Integer> list = Observable.just(1, 2, 3, 1).compose(removePairs()).toList()
.toBlocking().single();
assertEquals(Arrays.asList(3, 1), list);
}
@Test
public void testRemovePairsDoesNotRecurse() {
List<Integer> list = Observable.just(1, 1, 2, 2).compose(removePairs()).toList()
.toBlocking().single();
assertEquals(Arrays.asList(1, 2), list);
}
private static Transformer<Integer, Integer> removePairs() {
Func1<Integer, Boolean> isCandidateForFirst = new Func1<Integer, Boolean>() {
@Override
public Boolean call(Integer t) {
return t == 1;
}
};
Func2<Integer, Integer, Boolean> remove = new Func2<Integer, Integer, Boolean>() {
@Override
public Boolean call(Integer t1, Integer t2) {
return t1 == 1 && t2 == 2;
}
};
return Transformers.removePairs(isCandidateForFirst, remove);
}
@Test
public void testDelayWithPlayRate() {
TestSubscriber<Object> ts = TestSubscriber.create();
TestScheduler scheduler = new TestScheduler();
Func1<Integer, Long> time = new Func1<Integer, Long>() {
@Override
public Long call(Integer t) {
return (long) t;
}
};
Observable //
.just(1, 2, 3) //
.compose(Transformers.delay(time, Functions.constant0(0.001), 0, scheduler)) //
.subscribe(ts);
ts.assertNoValues();
scheduler.advanceTimeBy(1, TimeUnit.SECONDS);
ts.assertValue(1);
scheduler.advanceTimeBy(1, TimeUnit.SECONDS);
ts.assertValues(1, 2);
scheduler.advanceTimeBy(1, TimeUnit.SECONDS);
ts.assertValues(1, 2, 3);
ts.assertCompleted();
}
@Test
public void testSplitLongPattern() {
Iterator<String> iter = Strings.split(Observable.just("asdfqw", "erasdf"), "qwer")
.toBlocking().getIterator();
assertTrue(iter.hasNext());
assertEquals("asdf", iter.next());
assertTrue(iter.hasNext());
assertEquals("asdf", iter.next());
assertFalse(iter.hasNext());
}
@Test
public void testRepeatLast() {
List<Integer> list = Observable.just(1, 2).compose(Transformers.<Integer> repeatLast())
.take(5).toList().toBlocking().single();
assertEquals(Arrays.asList(1, 2, 2, 2, 2), list);
}
@Test
public void testRepeatLastOfEmptyIsEmpty() {
boolean empty = Observable.<Integer> empty().compose(Transformers.<Integer> repeatLast())
.isEmpty().toBlocking().single();
assertTrue(empty);
}
@Test
public void testRepeatLastOfOneElement() {
List<Integer> list = Observable.just(1).compose(Transformers.<Integer> repeatLast()).take(5)
.toList().toBlocking().single();
assertEquals(Arrays.asList(1, 1, 1, 1, 1), list);
}
@Test
public void testRepeatLastOfNoValuesThenError() {
TestSubscriber<Integer> ts = TestSubscriber.create();
Observable.<Integer> error(new IOException()).compose(Transformers.<Integer> repeatLast())
.subscribe(ts);
ts.assertNoValues();
ts.assertError(IOException.class);
}
@Test
public void testRepeatLastOfTwoValuesThenError() {
TestSubscriber<Integer> ts = TestSubscriber.create();
Observable.just(1, 2).concatWith(Observable.<Integer> error(new IOException()))
.compose(Transformers.<Integer> repeatLast()).subscribe(ts);
ts.assertValues(1,2);
ts.assertError(IOException.class);
}
}