15
15
*/
16
16
package rx .internal .operators ;
17
17
18
- import static org .junit .Assert .*;
18
+ import static org .junit .Assert .assertEquals ;
19
+ import static org .junit .Assert .fail ;
19
20
import static org .mockito .Matchers .any ;
20
21
import static org .mockito .Mockito .*;
21
22
22
- import java .util .concurrent .*;
23
- import java .util .concurrent .atomic .*;
23
+ import java .util .concurrent .CountDownLatch ;
24
+ import java .util .concurrent .ExecutorService ;
25
+ import java .util .concurrent .Executors ;
26
+ import java .util .concurrent .TimeUnit ;
27
+ import java .util .concurrent .atomic .AtomicBoolean ;
28
+ import java .util .concurrent .atomic .AtomicInteger ;
29
+ import java .util .concurrent .atomic .AtomicLong ;
24
30
25
31
import org .junit .Test ;
26
- import org .mockito .*;
32
+ import org .mockito .InOrder ;
33
+ import org .mockito .Mockito ;
27
34
28
- import rx .* ;
35
+ import rx .Observable ;
29
36
import rx .Observable .OnSubscribe ;
30
- import rx .functions .*;
37
+ import rx .Observer ;
38
+ import rx .Producer ;
39
+ import rx .Subscriber ;
40
+ import rx .Subscription ;
41
+ import rx .functions .Action0 ;
42
+ import rx .functions .Action1 ;
43
+ import rx .functions .Func1 ;
44
+ import rx .functions .Func2 ;
31
45
import rx .internal .util .RxRingBuffer ;
32
46
import rx .observables .GroupedObservable ;
33
47
import rx .observers .TestSubscriber ;
@@ -404,20 +418,25 @@ public void request(long n) {
404
418
}
405
419
return ;
406
420
}
407
- if (n > 0 && req .getAndAdd (1 ) == 0 ) {
421
+ if (n > 0 && req .getAndAdd (n ) == 0 ) {
408
422
int i = count .getAndIncrement ();
409
423
if (i < numFailures ) {
410
424
o .onNext ("beginningEveryTime" );
411
425
o .onError (new RuntimeException ("forced failure: " + count .get ()));
412
- } else
413
- if (i == numFailures ) {
414
- o .onNext ("beginningEveryTime" );
415
- } else
416
- if (i > numFailures ) {
417
- o .onNext ("onSuccessOnly" );
418
- o .onCompleted ();
426
+ req .decrementAndGet ();
427
+ } else {
428
+ do {
429
+ if (i == numFailures ) {
430
+ o .onNext ("beginningEveryTime" );
431
+ } else
432
+ if (i > numFailures ) {
433
+ o .onNext ("onSuccessOnly" );
434
+ o .onCompleted ();
435
+ break ;
436
+ }
437
+ i = count .getAndIncrement ();
438
+ } while (req .decrementAndGet () > 0 );
419
439
}
420
- req .decrementAndGet ();
421
440
}
422
441
}
423
442
});
@@ -675,15 +694,15 @@ public void testTimeoutWithRetry() {
675
694
}
676
695
677
696
@ Test (timeout = 10000 )
678
- public void testRetryWithBackpressure () {
679
- for (int i = 0 ; i < 200 ; i ++) {
697
+ public void testRetryWithBackpressure () throws InterruptedException {
698
+ final int NUM_RETRIES = RxRingBuffer .SIZE * 2 ;
699
+ for (int i = 0 ; i < 400 ; i ++) {
680
700
@ SuppressWarnings ("unchecked" )
681
701
Observer <String > observer = mock (Observer .class );
682
- int NUM_RETRIES = RxRingBuffer .SIZE * 2 ;
683
702
Observable <String > origin = Observable .create (new FuncWithErrors (NUM_RETRIES ));
684
703
TestSubscriber <String > ts = new TestSubscriber <String >(observer );
685
704
origin .retry ().observeOn (Schedulers .computation ()).unsafeSubscribe (ts );
686
- ts .awaitTerminalEvent ();
705
+ ts .awaitTerminalEvent (5 , TimeUnit . SECONDS );
687
706
688
707
InOrder inOrder = inOrder (observer );
689
708
// should have no errors
@@ -697,6 +716,49 @@ public void testRetryWithBackpressure() {
697
716
inOrder .verifyNoMoreInteractions ();
698
717
}
699
718
}
719
+ @ Test (timeout = 10000 )
720
+ public void testRetryWithBackpressureParallel () throws InterruptedException {
721
+ final int NUM_RETRIES = RxRingBuffer .SIZE * 2 ;
722
+ int ncpu = Runtime .getRuntime ().availableProcessors ();
723
+ ExecutorService exec = Executors .newFixedThreadPool (Math .max (ncpu / 2 , 1 ));
724
+ final AtomicInteger timeouts = new AtomicInteger ();
725
+ final AtomicInteger data = new AtomicInteger ();
726
+ int m = 2000 ;
727
+ final CountDownLatch cdl = new CountDownLatch (m );
728
+ for (int i = 0 ; i < m ; i ++) {
729
+ final int j = i ;
730
+ exec .execute (new Runnable () {
731
+ @ Override
732
+ public void run () {
733
+ final AtomicInteger nexts = new AtomicInteger ();
734
+ try {
735
+ Observable <String > origin = Observable .create (new FuncWithErrors (NUM_RETRIES ));
736
+ TestSubscriber <String > ts = new TestSubscriber <String >();
737
+ origin .retry ().observeOn (Schedulers .computation ()).unsafeSubscribe (ts );
738
+ ts .awaitTerminalEvent (2 , TimeUnit .SECONDS );
739
+ if (ts .getOnNextEvents ().size () != NUM_RETRIES + 2 ) {
740
+ data .incrementAndGet ();
741
+ }
742
+ if (ts .getOnErrorEvents ().size () != 0 ) {
743
+ data .incrementAndGet ();
744
+ }
745
+ if (ts .getOnCompletedEvents ().size () != 1 ) {
746
+ data .incrementAndGet ();
747
+ }
748
+ } catch (Throwable t ) {
749
+ timeouts .incrementAndGet ();
750
+ System .out .println (j + " | " + cdl .getCount () + " !!! " + nexts .get ());
751
+ }
752
+ cdl .countDown ();
753
+ }
754
+ });
755
+ }
756
+ exec .shutdown ();
757
+ cdl .await ();
758
+ assertEquals (0 , timeouts .get ());
759
+ assertEquals (0 , data .get ());
760
+
761
+ }
700
762
@ Test (timeout = 3000 )
701
763
public void testIssue1900 () throws InterruptedException {
702
764
@ SuppressWarnings ("unchecked" )
0 commit comments