|
48 | 48 | import rx.Observable.OnSubscribe;
|
49 | 49 | import rx.Observable.Transformer;
|
50 | 50 | import rx.exceptions.OnErrorNotImplementedException;
|
| 51 | +import rx.functions.Action0; |
51 | 52 | import rx.functions.Action1;
|
52 | 53 | import rx.functions.Action2;
|
53 | 54 | import rx.functions.Func1;
|
@@ -1124,4 +1125,126 @@ public String call(Integer t1) {
|
1124 | 1125 | ts.assertNoErrors();
|
1125 | 1126 | ts.assertReceivedOnNext(Arrays.asList("1", "2", "3"));
|
1126 | 1127 | }
|
| 1128 | + |
| 1129 | + @Test |
| 1130 | + public void testDoOnUnsubscribe() throws Exception { |
| 1131 | + int subCount = 3; |
| 1132 | + final CountDownLatch upperLatch = new CountDownLatch(subCount); |
| 1133 | + final CountDownLatch lowerLatch = new CountDownLatch(subCount); |
| 1134 | + final CountDownLatch onNextLatch = new CountDownLatch(subCount); |
| 1135 | + |
| 1136 | + final AtomicInteger upperCount = new AtomicInteger(); |
| 1137 | + final AtomicInteger lowerCount = new AtomicInteger(); |
| 1138 | + Observable<Long> longs = Observable |
| 1139 | + // The stream needs to be infinite to ensure the stream does not terminate |
| 1140 | + // before it is unsubscribed |
| 1141 | + .interval(50, TimeUnit.MILLISECONDS) |
| 1142 | + .doOnUnsubscribe(new Action0() { |
| 1143 | + // Test that upper stream will be notified for un-subscription |
| 1144 | + // from a child subscriber |
| 1145 | + @Override |
| 1146 | + public void call() { |
| 1147 | + upperLatch.countDown(); |
| 1148 | + upperCount.incrementAndGet(); |
| 1149 | + } |
| 1150 | + }) |
| 1151 | + .doOnNext(new Action1<Long>() { |
| 1152 | + @Override |
| 1153 | + public void call(Long aLong) { |
| 1154 | + // Ensure there is at least some onNext events before un-subscription happens |
| 1155 | + onNextLatch.countDown(); |
| 1156 | + } |
| 1157 | + }) |
| 1158 | + .doOnUnsubscribe(new Action0() { |
| 1159 | + // Test that lower stream will be notified for a direct un-subscription |
| 1160 | + @Override |
| 1161 | + public void call() { |
| 1162 | + lowerLatch.countDown(); |
| 1163 | + lowerCount.incrementAndGet(); |
| 1164 | + } |
| 1165 | + }); |
| 1166 | + |
| 1167 | + List<Subscription> subscriptions = new ArrayList<Subscription>(); |
| 1168 | + List<TestSubscriber> subscribers = new ArrayList<TestSubscriber>(); |
| 1169 | + |
| 1170 | + for(int i = 0; i < subCount; ++i) { |
| 1171 | + TestSubscriber<Long> subscriber = new TestSubscriber<Long>(); |
| 1172 | + subscriptions.add(longs.subscribe(subscriber)); |
| 1173 | + subscribers.add(subscriber); |
| 1174 | + } |
| 1175 | + |
| 1176 | + onNextLatch.await(); |
| 1177 | + for(int i = 0; i < subCount; ++i) { |
| 1178 | + subscriptions.get(i).unsubscribe(); |
| 1179 | + // Test that unsubscribe() method is not affected in any way |
| 1180 | + subscribers.get(i).assertUnsubscribed(); |
| 1181 | + } |
| 1182 | + |
| 1183 | + upperLatch.await(); |
| 1184 | + lowerLatch.await(); |
| 1185 | + assertEquals(String.format("There should exactly %d un-subscription events for upper stream", subCount), subCount, upperCount.get()); |
| 1186 | + assertEquals(String.format("There should exactly %d un-subscription events for lower stream", subCount), subCount, lowerCount.get()); |
| 1187 | + } |
| 1188 | + |
| 1189 | + @Test |
| 1190 | + public void testDoOnUnSubscribeWorksWithRefCount() throws Exception { |
| 1191 | + int subCount = 3; |
| 1192 | + final CountDownLatch upperLatch = new CountDownLatch(1); |
| 1193 | + final CountDownLatch lowerLatch = new CountDownLatch(1); |
| 1194 | + final CountDownLatch onNextLatch = new CountDownLatch(subCount); |
| 1195 | + |
| 1196 | + final AtomicInteger upperCount = new AtomicInteger(); |
| 1197 | + final AtomicInteger lowerCount = new AtomicInteger(); |
| 1198 | + Observable<Long> longs = Observable |
| 1199 | + // The stream needs to be infinite to ensure the stream does not terminate |
| 1200 | + // before it is unsubscribed |
| 1201 | + .interval(50, TimeUnit.MILLISECONDS) |
| 1202 | + .doOnUnsubscribe(new Action0() { |
| 1203 | + // Test that upper stream will be notified for un-subscription |
| 1204 | + @Override |
| 1205 | + public void call() { |
| 1206 | + upperLatch.countDown(); |
| 1207 | + upperCount.incrementAndGet(); |
| 1208 | + } |
| 1209 | + }) |
| 1210 | + .doOnNext(new Action1<Long>() { |
| 1211 | + @Override |
| 1212 | + public void call(Long aLong) { |
| 1213 | + // Ensure there is at least some onNext events before un-subscription happens |
| 1214 | + onNextLatch.countDown(); |
| 1215 | + } |
| 1216 | + }) |
| 1217 | + .doOnUnsubscribe(new Action0() { |
| 1218 | + // Test that lower stream will be notified for un-subscription |
| 1219 | + @Override |
| 1220 | + public void call() { |
| 1221 | + lowerLatch.countDown(); |
| 1222 | + lowerCount.incrementAndGet(); |
| 1223 | + } |
| 1224 | + }) |
| 1225 | + .publish() |
| 1226 | + .refCount(); |
| 1227 | + |
| 1228 | + List<Subscription> subscriptions = new ArrayList<Subscription>(); |
| 1229 | + List<TestSubscriber> subscribers = new ArrayList<TestSubscriber>(); |
| 1230 | + |
| 1231 | + for(int i = 0; i < subCount; ++i) { |
| 1232 | + TestSubscriber<Long> subscriber = new TestSubscriber<Long>(); |
| 1233 | + subscriptions.add(longs.subscribe(subscriber)); |
| 1234 | + subscribers.add(subscriber); |
| 1235 | + } |
| 1236 | + |
| 1237 | + onNextLatch.await(); |
| 1238 | + for(int i = 0; i < subCount; ++i) { |
| 1239 | + subscriptions.get(i).unsubscribe(); |
| 1240 | + // Test that unsubscribe() method is not affected in any way |
| 1241 | + subscribers.get(i).assertUnsubscribed(); |
| 1242 | + } |
| 1243 | + |
| 1244 | + upperLatch.await(); |
| 1245 | + lowerLatch.await(); |
| 1246 | + assertEquals("There should exactly 1 un-subscription events for upper stream", 1, upperCount.get()); |
| 1247 | + assertEquals("There should exactly 1 un-subscription events for lower stream", 1, lowerCount.get()); |
| 1248 | + |
| 1249 | + } |
1127 | 1250 | }
|
0 commit comments