17
17
18
18
import org .junit .Before ;
19
19
import org .junit .Test ;
20
+ import org .junit .runner .RunWith ;
21
+ import org .junit .runners .JUnit4 ;
20
22
import org .mockito .MockitoAnnotations ;
21
23
import rx .Observable ;
22
24
import rx .Observer ;
23
25
import rx .Subscription ;
24
26
import rx .observables .ConnectableObservable ;
25
27
import rx .subscriptions .Subscriptions ;
28
+ import rx .util .functions .Action0 ;
26
29
import rx .util .functions .Func1 ;
27
30
28
31
import static org .mockito .Mockito .*;
@@ -38,17 +41,38 @@ public static <T> Func1<Observer<T>, Subscription> refCount(ConnectableObservabl
38
41
39
42
private static class RefCount <T > implements Func1 <Observer <T >, Subscription > {
40
43
private final ConnectableObservable <T > innerConnectableObservable ;
44
+ private final Object gate = new Object ();
45
+ private int count = 0 ;
46
+ private Subscription connection = null ;
41
47
42
48
public RefCount (ConnectableObservable <T > innerConnectableObservable ) {
43
49
this .innerConnectableObservable = innerConnectableObservable ;
44
50
}
45
51
46
52
@ Override
47
53
public Subscription call (Observer <T > observer ) {
48
- throw new UnsupportedOperationException ();
54
+ final Subscription subscription = innerConnectableObservable .subscribe (observer );
55
+ synchronized (gate ) {
56
+ if (count ++ == 0 ) {
57
+ connection = innerConnectableObservable .connect ();
58
+ }
59
+ }
60
+ return Subscriptions .create (new Action0 () {
61
+ @ Override
62
+ public void call () {
63
+ synchronized (gate ) {
64
+ if (--count == 0 ) {
65
+ connection .unsubscribe ();
66
+ connection = null ;
67
+ }
68
+ }
69
+ subscription .unsubscribe ();
70
+ }
71
+ });
49
72
}
50
73
}
51
74
75
+ @ RunWith (JUnit4 .class )
52
76
public static class UnitTest {
53
77
54
78
@ Before
@@ -58,8 +82,10 @@ public void setUp() {
58
82
59
83
@ Test
60
84
public void subscriptionToUnderlyingOnFirstSubscription () {
85
+ @ SuppressWarnings ("unchecked" )
61
86
ConnectableObservable <Integer > connectable = mock (ConnectableObservable .class );
62
87
Observable <Integer > refCounted = Observable .create (refCount (connectable ));
88
+ @ SuppressWarnings ("unchecked" )
63
89
Observer <Integer > observer = mock (Observer .class );
64
90
when (connectable .subscribe (observer )).thenReturn (Subscriptions .empty ());
65
91
when (connectable .connect ()).thenReturn (Subscriptions .empty ());
@@ -70,17 +96,53 @@ public void subscriptionToUnderlyingOnFirstSubscription() {
70
96
71
97
@ Test
72
98
public void noSubscriptionToUnderlyingOnSecondSubscription () {
73
-
99
+ @ SuppressWarnings ("unchecked" )
100
+ ConnectableObservable <Integer > connectable = mock (ConnectableObservable .class );
101
+ Observable <Integer > refCounted = Observable .create (refCount (connectable ));
102
+ @ SuppressWarnings ("unchecked" )
103
+ Observer <Integer > observer = mock (Observer .class );
104
+ when (connectable .subscribe (observer )).thenReturn (Subscriptions .empty ());
105
+ when (connectable .connect ()).thenReturn (Subscriptions .empty ());
106
+ refCounted .subscribe (observer );
107
+ refCounted .subscribe (observer );
108
+ verify (connectable , times (2 )).subscribe (observer );
109
+ verify (connectable , times (1 )).connect ();
74
110
}
75
111
76
112
@ Test
77
113
public void unsubscriptionFromUnderlyingOnLastUnsubscription () {
78
-
114
+ @ SuppressWarnings ("unchecked" )
115
+ ConnectableObservable <Integer > connectable = mock (ConnectableObservable .class );
116
+ Observable <Integer > refCounted = Observable .create (refCount (connectable ));
117
+ @ SuppressWarnings ("unchecked" )
118
+ Observer <Integer > observer = mock (Observer .class );
119
+ Subscription underlying = mock (Subscription .class );
120
+ when (connectable .subscribe (observer )).thenReturn (underlying );
121
+ Subscription connection = mock (Subscription .class );
122
+ when (connectable .connect ()).thenReturn (connection );
123
+ Subscription first = refCounted .subscribe (observer );
124
+ first .unsubscribe ();
125
+ verify (underlying , times (1 )).unsubscribe ();
126
+ verify (connection , times (1 )).unsubscribe ();
79
127
}
80
128
81
129
@ Test
82
130
public void noUnsubscriptionFromUnderlyingOnFirstUnsubscription () {
83
-
131
+ @ SuppressWarnings ("unchecked" )
132
+ ConnectableObservable <Integer > connectable = mock (ConnectableObservable .class );
133
+ Observable <Integer > refCounted = Observable .create (refCount (connectable ));
134
+ @ SuppressWarnings ("unchecked" )
135
+ Observer <Integer > observer = mock (Observer .class );
136
+ Subscription underlying = mock (Subscription .class );
137
+ when (connectable .subscribe (observer )).thenReturn (underlying );
138
+ Subscription connection = mock (Subscription .class );
139
+ when (connectable .connect ()).thenReturn (connection );
140
+ Subscription first = refCounted .subscribe (observer );
141
+ Subscription second = refCounted .subscribe (observer );
142
+ first .unsubscribe ();
143
+ second .unsubscribe ();
144
+ verify (underlying , times (2 )).unsubscribe ();
145
+ verify (connection , times (1 )).unsubscribe ();
84
146
}
85
147
}
86
148
}
0 commit comments