• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "../test.h"
2 #include <rxcpp/operators/rx-map.hpp>
3 #include <rxcpp/operators/rx-take_until.hpp>
4 
5 SCENARIO("take_until trigger on_next", "[take_until][take][operators]"){
6     GIVEN("2 sources"){
7         auto sc = rxsc::make_test();
8         auto w = sc.create_worker();
9         const rxsc::test::messages<int> on;
10 
11         auto xs = sc.make_hot_observable({
12             on.next(150, 1),
13             on.next(210, 2),
14             on.next(220, 3),
15             on.next(230, 4),
16             on.next(240, 5),
17             on.completed(250)
18         });
19 
20         auto ys = sc.make_hot_observable({
21             on.next(150, 1),
22             on.next(225, 99),
23             on.completed(230)
24         });
25 
26         WHEN("one is taken until the other emits a marble"){
27 
28             auto res = w.start(
__anonda5e5f430102() 29                 [xs, ys]() {
30                 return xs
31                     | rxo::take_until(ys)
32                     // forget type to workaround lambda deduction bug on msvc 2013
33                     | rxo::as_dynamic();
34             }
35             );
36 
37             THEN("the output only contains items sent while subscribed"){
38                 auto required = rxu::to_vector({
39                     on.next(210, 2),
40                     on.next(220, 3),
41                     on.completed(225)
42                 });
43                 auto actual = res.get_observer().messages();
44                 REQUIRE(required == actual);
45             }
46 
47             THEN("there was 1 subscription/unsubscription to the source"){
48                 auto required = rxu::to_vector({
49                     on.subscribe(200, 225)
50                 });
51                 auto actual = xs.subscriptions();
52                 REQUIRE(required == actual);
53             }
54 
55             THEN("there was 1 subscription/unsubscription to the trigger"){
56                 auto required = rxu::to_vector({
57                     on.subscribe(200, 225)
58                 });
59                 auto actual = ys.subscriptions();
60                 REQUIRE(required == actual);
61             }
62 
63         }
64     }
65 }
66 
67 SCENARIO("take_until, preempt some data next", "[take_until][take][operators]"){
68     GIVEN("2 sources"){
69         auto sc = rxsc::make_test();
70         auto w = sc.create_worker();
71         const rxsc::test::messages<int> on;
72 
73         auto l = sc.make_hot_observable({
74             on.next(150, 1),
75             on.next(210, 2),
76             on.next(220, 3),
77             on.next(230, 4),
78             on.next(240, 5),
79             on.completed(250)
80         });
81 
82         auto r = sc.make_hot_observable({
83             on.next(150, 1),
84             on.next(225, 99),
85             on.completed(230)
86         });
87 
88         WHEN("one is taken until the other emits a marble"){
89 
90             auto res = w.start(
__anonda5e5f430202() 91                 [l, r]() {
92                 return l
93                     .take_until(r)
94                     // forget type to workaround lambda deduction bug on msvc 2013
95                     .as_dynamic();
96             }
97             );
98 
99             THEN("the output only contains items sent while subscribed"){
100                 auto required = rxu::to_vector({
101                     on.next(210, 2),
102                     on.next(220, 3),
103                     on.completed(225)
104                 });
105                 auto actual = res.get_observer().messages();
106                 REQUIRE(required == actual);
107             }
108 
109             THEN("there was 1 subscription/unsubscription to the source"){
110                 auto required = rxu::to_vector({
111                     on.subscribe(200, 225)
112                 });
113                 auto actual = l.subscriptions();
114                 REQUIRE(required == actual);
115             }
116 
117             THEN("there was 1 subscription/unsubscription to the trigger"){
118                 auto required = rxu::to_vector({
119                     on.subscribe(200, 225)
120                 });
121                 auto actual = r.subscriptions();
122                 REQUIRE(required == actual);
123             }
124 
125         }
126     }
127 }
128 
129 SCENARIO("take_until, preempt some data error", "[take_until][take][operators]"){
130     GIVEN("2 sources"){
131         auto sc = rxsc::make_test();
132         auto w = sc.create_worker();
133         const rxsc::test::messages<int> on;
134 
135         std::runtime_error ex("take_until on_error from source");
136 
137         auto l = sc.make_hot_observable({
138             on.next(150, 1),
139             on.next(210, 2),
140             on.next(220, 3),
141             on.next(230, 4),
142             on.next(240, 5),
143             on.completed(250)
144         });
145 
146         auto r = sc.make_hot_observable({
147             on.next(150, 1),
148             on.error(225, ex)
149         });
150 
151         WHEN("one is taken until the other emits a marble"){
152 
153             auto res = w.start(
__anonda5e5f430302() 154                 [l, r]() {
155                 return l
156                     .take_until(r)
157                     // forget type to workaround lambda deduction bug on msvc 2013
158                     .as_dynamic();
159             }
160             );
161 
162             THEN("the output only contains items sent while subscribed"){
163                 auto required = rxu::to_vector({
164                     on.next(210, 2),
165                     on.next(220, 3),
166                     on.error(225, ex)
167                 });
168                 auto actual = res.get_observer().messages();
169                 REQUIRE(required == actual);
170             }
171 
172             THEN("there was 1 subscription/unsubscription to the source"){
173                 auto required = rxu::to_vector({
174                     on.subscribe(200, 225)
175                 });
176                 auto actual = l.subscriptions();
177                 REQUIRE(required == actual);
178             }
179 
180             THEN("there was 1 subscription/unsubscription to the trigger"){
181                 auto required = rxu::to_vector({
182                     on.subscribe(200, 225)
183                 });
184                 auto actual = r.subscriptions();
185                 REQUIRE(required == actual);
186             }
187 
188         }
189     }
190 }
191 
192 SCENARIO("take_until, no-preempt some data empty", "[take_until][take][operators]"){
193     GIVEN("2 sources"){
194         auto sc = rxsc::make_test();
195         auto w = sc.create_worker();
196         const rxsc::test::messages<int> on;
197 
198         auto l = sc.make_hot_observable({
199             on.next(150, 1),
200             on.next(210, 2),
201             on.next(220, 3),
202             on.next(230, 4),
203             on.next(240, 5),
204             on.completed(250)
205         });
206 
207         auto r = sc.make_hot_observable({
208             on.next(150, 1),
209             on.completed(225)
210         });
211 
212         WHEN("one is taken until the other emits a marble"){
213 
214             auto res = w.start(
__anonda5e5f430402() 215                 [l, r]() {
216                 return l
217                     .take_until(r)
218                     // forget type to workaround lambda deduction bug on msvc 2013
219                     .as_dynamic();
220             }
221             );
222 
223             THEN("the output only contains items sent while subscribed"){
224                 auto required = rxu::to_vector({
225                     on.next(210, 2),
226                     on.next(220, 3),
227                     on.next(230, 4),
228                     on.next(240, 5),
229                     on.completed(250)
230                 });
231                 auto actual = res.get_observer().messages();
232                 REQUIRE(required == actual);
233             }
234 
235             THEN("there was 1 subscription/unsubscription to the source"){
236                 auto required = rxu::to_vector({
237                     on.subscribe(200, 250)
238                 });
239                 auto actual = l.subscriptions();
240                 REQUIRE(required == actual);
241             }
242 
243             THEN("there was 1 subscription/unsubscription to the trigger"){
244                 auto required = rxu::to_vector({
245                     on.subscribe(200, 225)
246                 });
247                 auto actual = r.subscriptions();
248                 REQUIRE(required == actual);
249             }
250 
251         }
252     }
253 }
254 
255 SCENARIO("take_until, no-preempt some data never", "[take_until][take][operators]"){
256     GIVEN("2 sources"){
257         auto sc = rxsc::make_test();
258         auto w = sc.create_worker();
259         const rxsc::test::messages<int> on;
260 
261         auto l = sc.make_hot_observable({
262             on.next(150, 1),
263             on.next(210, 2),
264             on.next(220, 3),
265             on.next(230, 4),
266             on.next(240, 5),
267             on.completed(250)
268         });
269 
270         auto r = sc.make_hot_observable({
271             on.next(150, 1)
272         });
273 
274         WHEN("one is taken until the other emits a marble"){
275 
276             auto res = w.start(
__anonda5e5f430502() 277                 [l, r]() {
278                 return l
279                     .take_until(r)
280                     // forget type to workaround lambda deduction bug on msvc 2013
281                     .as_dynamic();
282             }
283             );
284 
285             THEN("the output only contains items sent while subscribed"){
286                 auto required = rxu::to_vector({
287                     on.next(210, 2),
288                     on.next(220, 3),
289                     on.next(230, 4),
290                     on.next(240, 5),
291                     on.completed(250)
292                 });
293                 auto actual = res.get_observer().messages();
294                 REQUIRE(required == actual);
295             }
296 
297             THEN("there was 1 subscription/unsubscription to the source"){
298                 auto required = rxu::to_vector({
299                     on.subscribe(200, 250)
300                 });
301                 auto actual = l.subscriptions();
302                 REQUIRE(required == actual);
303             }
304 
305             THEN("there was 1 subscription/unsubscription to the trigger"){
306                 auto required = rxu::to_vector({
307                     on.subscribe(200, 250)
308                 });
309                 auto actual = r.subscriptions();
310                 REQUIRE(required == actual);
311             }
312 
313         }
314     }
315 }
316 
317 SCENARIO("take_until, preempt never next", "[take_until][take][operators]"){
318     GIVEN("2 sources"){
319         auto sc = rxsc::make_test();
320         auto w = sc.create_worker();
321         const rxsc::test::messages<int> on;
322 
323         auto l = sc.make_hot_observable({
324             on.next(150, 1)
325         });
326 
327         auto r = sc.make_hot_observable({
328             on.next(150, 1),
329             on.next(225, 2), //!
330             on.completed(250)
331         });
332 
333         WHEN("one is taken until the other emits a marble"){
334 
335             auto res = w.start(
__anonda5e5f430602() 336                 [l, r]() {
337                 return l
338                     .take_until(r)
339                     // forget type to workaround lambda deduction bug on msvc 2013
340                     .as_dynamic();
341             }
342             );
343 
344             THEN("the output only contains items sent while subscribed"){
345                 auto required = rxu::to_vector({
346                     on.completed(225)
347                 });
348                 auto actual = res.get_observer().messages();
349                 REQUIRE(required == actual);
350             }
351 
352             THEN("there was 1 subscription/unsubscription to the source"){
353                 auto required = rxu::to_vector({
354                     on.subscribe(200, 225)
355                 });
356                 auto actual = l.subscriptions();
357                 REQUIRE(required == actual);
358             }
359 
360             THEN("there was 1 subscription/unsubscription to the trigger"){
361                 auto required = rxu::to_vector({
362                     on.subscribe(200, 225)
363                 });
364                 auto actual = r.subscriptions();
365                 REQUIRE(required == actual);
366             }
367 
368         }
369     }
370 }
371 
372 SCENARIO("take_until, preempt never error", "[take_until][take][operators]"){
373     GIVEN("2 sources"){
374         auto sc = rxsc::make_test();
375         auto w = sc.create_worker();
376         const rxsc::test::messages<int> on;
377 
378         std::runtime_error ex("take_until on_error from source");
379 
380         auto l = sc.make_hot_observable({
381             on.next(150, 1)
382         });
383 
384         auto r = sc.make_hot_observable({
385             on.next(150, 1),
386             on.error(225, ex)
387         });
388 
389         WHEN("one is taken until the other emits a marble"){
390 
391             auto res = w.start(
__anonda5e5f430702() 392                 [l, r]() {
393                 return l
394                     .take_until(r)
395                     // forget type to workaround lambda deduction bug on msvc 2013
396                     .as_dynamic();
397             }
398             );
399 
400             THEN("the output only contains items sent while subscribed"){
401                 auto required = rxu::to_vector({
402                     on.error(225, ex)
403                 });
404                 auto actual = res.get_observer().messages();
405                 REQUIRE(required == actual);
406             }
407 
408             THEN("there was 1 subscription/unsubscription to the source"){
409                 auto required = rxu::to_vector({
410                     on.subscribe(200, 225)
411                 });
412                 auto actual = l.subscriptions();
413                 REQUIRE(required == actual);
414             }
415 
416             THEN("there was 1 subscription/unsubscription to the trigger"){
417                 auto required = rxu::to_vector({
418                     on.subscribe(200, 225)
419                 });
420                 auto actual = r.subscriptions();
421                 REQUIRE(required == actual);
422             }
423 
424         }
425     }
426 }
427 
428 SCENARIO("take_until, no-preempt never empty", "[take_until][take][operators]"){
429     GIVEN("2 sources"){
430         auto sc = rxsc::make_test();
431         auto w = sc.create_worker();
432         const rxsc::test::messages<int> on;
433 
434         auto l = sc.make_hot_observable({
435             on.next(150, 1)
436         });
437 
438         auto r = sc.make_hot_observable({
439             on.next(150, 1),
440             on.completed(225)
441         });
442 
443         WHEN("one is taken until the other emits a marble"){
444 
445             auto res = w.start(
__anonda5e5f430802() 446                 [l, r]() {
447                 return l
448                     .take_until(r)
449                     // forget type to workaround lambda deduction bug on msvc 2013
450                     .as_dynamic();
451             }
452             );
453 
454             THEN("the output only contains items sent while subscribed"){
455                 auto required = std::vector<rxsc::test::messages<int>::recorded_type>();
456                 auto actual = res.get_observer().messages();
457                 REQUIRE(required == actual);
458             }
459 
460             THEN("there was 1 subscription/unsubscription to the source"){
461                 auto required = rxu::to_vector({
462                     on.subscribe(200, 1000 /* can't dispose prematurely, could be in flight to dispatch OnError */)
463                 });
464                 auto actual = l.subscriptions();
465                 REQUIRE(required == actual);
466             }
467 
468             THEN("there was 1 subscription/unsubscription to the trigger"){
469                 auto required = rxu::to_vector({
470                     on.subscribe(200, 225)
471                 });
472                 auto actual = r.subscriptions();
473                 REQUIRE(required == actual);
474             }
475 
476         }
477     }
478 }
479 
480 SCENARIO("take_until, no-preempt never never", "[take_until][take][operators]"){
481     GIVEN("2 sources"){
482         auto sc = rxsc::make_test();
483         auto w = sc.create_worker();
484         const rxsc::test::messages<int> on;
485 
486         auto l = sc.make_hot_observable({
487             on.next(150, 1)
488         });
489 
490         auto r = sc.make_hot_observable({
491             on.next(150, 1)
492         });
493 
494         WHEN("one is taken until the other emits a marble"){
495 
496             auto res = w.start(
__anonda5e5f430902() 497                 [l, r]() {
498                 return l
499                     .take_until(r)
500                     // forget type to workaround lambda deduction bug on msvc 2013
501                     .as_dynamic();
502             }
503             );
504 
505             THEN("the output only contains items sent while subscribed"){
506                 auto required = std::vector<rxsc::test::messages<int>::recorded_type>();
507                 auto actual = res.get_observer().messages();
508                 REQUIRE(required == actual);
509             }
510 
511             THEN("there was 1 subscription/unsubscription to the source"){
512                 auto required = rxu::to_vector({
513                     on.subscribe(200, 1000)
514                 });
515                 auto actual = l.subscriptions();
516                 REQUIRE(required == actual);
517             }
518 
519             THEN("there was 1 subscription/unsubscription to the trigger"){
520                 auto required = rxu::to_vector({
521                     on.subscribe(200, 1000)
522                 });
523                 auto actual = r.subscriptions();
524                 REQUIRE(required == actual);
525             }
526 
527         }
528     }
529 }
530 
531 SCENARIO("take_until, preempt before first produced", "[take_until][take][operators]"){
532     GIVEN("2 sources"){
533         auto sc = rxsc::make_test();
534         auto w = sc.create_worker();
535         const rxsc::test::messages<int> on;
536 
537         auto l = sc.make_hot_observable({
538             on.next(150, 1),
539             on.next(230, 2),
540             on.completed(240)
541         });
542 
543         auto r = sc.make_hot_observable({
544             on.next(150, 1),
545             on.next(210, 2), //!
546             on.completed(220)
547         });
548 
549         WHEN("one is taken until the other emits a marble"){
550 
551             auto res = w.start(
__anonda5e5f430a02() 552                 [l, r]() {
553                 return l
554                     .take_until(r)
555                     // forget type to workaround lambda deduction bug on msvc 2013
556                     .as_dynamic();
557             }
558             );
559 
560             THEN("the output only contains items sent while subscribed"){
561                 auto required = rxu::to_vector({
562                     on.completed(210)
563                 });
564                 auto actual = res.get_observer().messages();
565                 REQUIRE(required == actual);
566             }
567 
568             THEN("there was 1 subscription/unsubscription to the source"){
569                 auto required = rxu::to_vector({
570                     on.subscribe(200, 210)
571                 });
572                 auto actual = l.subscriptions();
573                 REQUIRE(required == actual);
574             }
575 
576             THEN("there was 1 subscription/unsubscription to the trigger"){
577                 auto required = rxu::to_vector({
578                     on.subscribe(200, 210)
579                 });
580                 auto actual = r.subscriptions();
581                 REQUIRE(required == actual);
582             }
583 
584         }
585     }
586 }
587 
588 SCENARIO("take_until, preempt before first produced, remain silent and proper unsubscribed", "[take_until][take][operators]"){
589     GIVEN("2 sources"){
590         auto sc = rxsc::make_test();
591         auto w = sc.create_worker();
592         const rxsc::test::messages<int> on;
593 
594         bool sourceNotDisposed = false;
595 
596         auto l = sc.make_hot_observable({
597             on.next(150, 1),
598             on.error(215, std::runtime_error("error in unsubscribed stream")), // should not come
599             on.completed(240)
600         });
601 
602         auto r = sc.make_hot_observable({
603             on.next(150, 1),
604             on.next(210, 2), //!
605             on.completed(220)
606         });
607 
608         WHEN("one is taken until the other emits a marble"){
609 
610             auto res = w.start(
__anonda5e5f430b02() 611                 [l, r, &sourceNotDisposed]() {
612                 return l
613                     .map([&sourceNotDisposed](int v){sourceNotDisposed = true; return v; })
614                     .take_until(r)
615                     // forget type to workaround lambda deduction bug on msvc 2013
616                     .as_dynamic();
617             }
618             );
619 
620             THEN("the output only contains items sent while subscribed"){
621                 auto required = rxu::to_vector({
622                     on.completed(210)
623                 });
624                 auto actual = res.get_observer().messages();
625                 REQUIRE(required == actual);
626             }
627 
628             THEN("signal disposed"){
629                 auto required = false;
630                 auto actual = sourceNotDisposed;
631                 REQUIRE(required == actual);
632             }
633 
634         }
635     }
636 }
637 
638 SCENARIO("take_until, no-preempt after last produced, proper unsubscribe signal", "[take_until][take][operators]"){
639     GIVEN("2 sources"){
640         auto sc = rxsc::make_test();
641         auto w = sc.create_worker();
642         const rxsc::test::messages<int> on;
643 
644         bool signalNotDisposed = false;
645 
646         auto l = sc.make_hot_observable({
647             on.next(150, 1),
648             on.next(230, 2),
649             on.completed(240)
650         });
651 
652         auto r = sc.make_hot_observable({
653             on.next(150, 1),
654             on.next(250, 2),
655             on.completed(260)
656         });
657 
658         WHEN("one is taken until the other emits a marble"){
659 
660             auto res = w.start(
__anonda5e5f430d02() 661                 [l, r, &signalNotDisposed]() {
662                 return l
663                     .take_until(r
664                     .map([&signalNotDisposed](int v){signalNotDisposed = true; return v; }))
665                     // forget type to workaround lambda deduction bug on msvc 2013
666                     .as_dynamic();
667             }
668             );
669 
670             THEN("the output only contains items sent while subscribed"){
671                 auto required = rxu::to_vector({
672                     on.next(230, 2),
673                     on.completed(240)
674                 });
675                 auto actual = res.get_observer().messages();
676                 REQUIRE(required == actual);
677             }
678 
679             THEN("signal disposed"){
680                 auto required = false;
681                 auto actual = signalNotDisposed;
682                 REQUIRE(required == actual);
683             }
684 
685         }
686     }
687 }
688 
689 SCENARIO("take_until, error some", "[take_until][take][operators]"){
690     GIVEN("2 sources"){
691         auto sc = rxsc::make_test();
692         auto w = sc.create_worker();
693         const rxsc::test::messages<int> on;
694 
695         std::runtime_error ex("take_until on_error from source");
696 
697         auto l = sc.make_hot_observable({
698             on.next(150, 1),
699             on.error(225, ex)
700         });
701 
702         auto r = sc.make_hot_observable({
703             on.next(150, 1),
704             on.next(240, 2)
705         });
706 
707         WHEN("one is taken until the other emits a marble"){
708 
709             auto res = w.start(
__anonda5e5f430f02() 710                 [l, r]() {
711                 return l
712                     .take_until(r)
713                     // forget type to workaround lambda deduction bug on msvc 2013
714                     .as_dynamic();
715             }
716             );
717 
718             THEN("the output only contains items sent while subscribed"){
719                 auto required = rxu::to_vector({
720                     on.error(225, ex)
721                 });
722                 auto actual = res.get_observer().messages();
723                 REQUIRE(required == actual);
724             }
725 
726             THEN("there was 1 subscription/unsubscription to the source"){
727                 auto required = rxu::to_vector({
728                     on.subscribe(200, 225)
729                 });
730                 auto actual = l.subscriptions();
731                 REQUIRE(required == actual);
732             }
733 
734             THEN("there was 1 subscription/unsubscription to the trigger"){
735                 auto required = rxu::to_vector({
736                     on.subscribe(200, 225)
737                 });
738                 auto actual = r.subscriptions();
739                 REQUIRE(required == actual);
740             }
741 
742         }
743     }
744 }
745 
746 SCENARIO("take_until trigger on time point", "[take_until][take][operators]"){
747     GIVEN("a source and a time point"){
748         auto sc = rxsc::make_test();
749         auto so = rx::synchronize_in_one_worker(sc);
750         auto w = sc.create_worker();
751         const rxsc::test::messages<int> on;
752 
753         auto xs = sc.make_hot_observable({
754             on.next(150, 1),
755             on.next(210, 2),
756             on.next(220, 3),
757             on.next(230, 4),
758             on.next(240, 5),
759             on.completed(250)
760         });
761 
762         auto t = sc.to_time_point(225);
763 
764         WHEN("invoked with a time point"){
765 
766             auto res = w.start(
__anonda5e5f431002() 767                 [&]() {
768                 return xs
769                     | rxo::take_until(t, so)
770                     // forget type to workaround lambda deduction bug on msvc 2013
771                     | rxo::as_dynamic();
772             }
773             );
774 
775             THEN("the output only contains items sent while subscribed"){
776                 auto required = rxu::to_vector({
777                     on.next(211, 2),
778                     on.next(221, 3),
779                     on.completed(226)
780                 });
781                 auto actual = res.get_observer().messages();
782                 REQUIRE(required == actual);
783             }
784 
785             THEN("there was 1 subscription/unsubscription to the source"){
786                 auto required = rxu::to_vector({
787                     on.subscribe(200, 226)
788                 });
789                 auto actual = xs.subscriptions();
790                 REQUIRE(required == actual);
791             }
792         }
793     }
794 }
795