• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "../test.h"
2 
3 SCENARIO("scope, cold observable", "[scope][sources]"){
4     GIVEN("a test cold observable of ints"){
5         auto sc = rxsc::make_test();
6         auto w = sc.create_worker();
7         const rxsc::test::messages<int> on;
8 
9         rxu::detail::maybe<rx::test::testable_observable<int>> xs;
10 
11         typedef rx::resource<std::vector<int>> resource;
12 
13         WHEN("created by scope"){
14 
15             auto res = w.start(
__anonbc61a3d20102() 16                 [&]() {
17                     return rx::observable<>::
18                         scope(
19                             [&](){
20                                 return resource(rxu::to_vector({1, 2, 3, 4, 5}));
21                             },
22                             [&](resource r){
23                                 auto msg = std::vector<rxsc::test::messages<int>::recorded_type>();
24                                 int time = 10;
25                                 auto values = r.get();
26                                 std::for_each(values.begin(), values.end(), [&](int &v){
27                                     msg.push_back(on.next(time, v));
28                                     time += 10;
29                                 });
30                                 msg.push_back(on.completed(time));
31                                 xs.reset(sc.make_cold_observable(msg));
32                                 return xs.get();
33                             }
34                         )
35                         // forget type to workaround lambda deduction bug on msvc 2013
36                         .as_dynamic();
37                 }
38             );
39 
40             THEN("the output stops on completion"){
41                 auto required = rxu::to_vector({
42                     on.next(210, 1),
43                     on.next(220, 2),
44                     on.next(230, 3),
45                     on.next(240, 4),
46                     on.next(250, 5),
47                     on.completed(260)
48                 });
49                 auto actual = res.get_observer().messages();
50                 REQUIRE(required == actual);
51             }
52 
53             THEN("there was one subscription and one unsubscription"){
54                 auto required = rxu::to_vector({
55                     on.subscribe(200, 260)
56                 });
57                 auto actual = xs.get().subscriptions();
58                 REQUIRE(required == actual);
59             }
60         }
61     }
62 }
63 
64 SCENARIO("scope, hot observable", "[scope][sources]"){
65     GIVEN("a test hot observable of ints"){
66         auto sc = rxsc::make_test();
67         auto w = sc.create_worker();
68         const rxsc::test::messages<int> on;
69 
70         rxu::detail::maybe<rx::test::testable_observable<int>> xs;
71 
72         typedef rx::resource<std::vector<int>> resource;
73 
74         WHEN("created by scope"){
75 
76             auto res = w.start(
__anonbc61a3d20502() 77                 [&]() {
78                     return rx::observable<>::
79                         scope(
80                             [&](){
81                                 return resource(rxu::to_vector({1, 2, 3, 4, 5}));
82                             },
83                             [&](resource r){
84                                 auto msg = std::vector<rxsc::test::messages<int>::recorded_type>();
85                                 int time = 210;
86                                 auto values = r.get();
87                                 std::for_each(values.begin(), values.end(), [&](int &v){
88                                     msg.push_back(on.next(time, v));
89                                     time += 10;
90                                 });
91                                 msg.push_back(on.completed(time));
92                                 xs.reset(sc.make_hot_observable(msg));
93                                 return xs.get();
94                             }
95                         )
96                         // forget type to workaround lambda deduction bug on msvc 2013
97                         .as_dynamic();
98                 }
99             );
100 
101             THEN("the output stops on completion"){
102                 auto required = rxu::to_vector({
103                     on.next(210, 1),
104                     on.next(220, 2),
105                     on.next(230, 3),
106                     on.next(240, 4),
107                     on.next(250, 5),
108                     on.completed(260)
109                 });
110                 auto actual = res.get_observer().messages();
111                 REQUIRE(required == actual);
112             }
113 
114             THEN("there was one subscription and one unsubscription"){
115                 auto required = rxu::to_vector({
116                     on.subscribe(200, 260)
117                 });
118                 auto actual = xs.get().subscriptions();
119                 REQUIRE(required == actual);
120             }
121         }
122     }
123 }
124 
125 SCENARIO("scope, complete", "[scope][sources]"){
126     GIVEN("a test cold observable of ints"){
127         auto sc = rxsc::make_test();
128         auto w = sc.create_worker();
129         const rxsc::test::messages<int> on;
130 
131         int resource_factory_invoked = 0;
132         int observable_factory_invoked = 0;
133 
134         rxu::detail::maybe<rx::test::testable_observable<int>> xs;
135 
136         typedef rx::resource<int> resource;
137 
138         WHEN("created by scope"){
139 
140             auto res = w.start(
__anonbc61a3d20902() 141                 [&]() {
142                     return rx::observable<>::
143                         scope(
144                             [&](){
145                                 ++resource_factory_invoked;
146                                 return resource(sc.clock());
147                             },
148                             [&](resource r){
149                                 ++observable_factory_invoked;
150                                 xs.reset(sc.make_cold_observable(rxu::to_vector({
151                                     on.next(100, r.get()),
152                                     on.completed(200)
153                                 })));
154                                 return xs.get();
155                             }
156                         )
157                         // forget type to workaround lambda deduction bug on msvc 2013
158                         .as_dynamic();
159                 }
160             );
161 
162             THEN("Resource factory is used once"){
163                 REQUIRE(1 == resource_factory_invoked);
164             }
165 
166             THEN("Observable factory is used once"){
167                 REQUIRE(1 == observable_factory_invoked);
168             }
169 
170             THEN("the output stops on completion"){
171                 auto required = rxu::to_vector({
172                     on.next(300, 200),
173                     on.completed(400)
174                 });
175                 auto actual = res.get_observer().messages();
176                 REQUIRE(required == actual);
177             }
178 
179             THEN("there was one subscription and one unsubscription"){
180                 auto required = rxu::to_vector({
181                     on.subscribe(200, 400)
182                 });
183                 auto actual = xs.get().subscriptions();
184                 REQUIRE(required == actual);
185             }
186         }
187     }
188 }
189 
190 SCENARIO("scope, error", "[scope][sources]"){
191     GIVEN("a test cold observable of ints"){
192         auto sc = rxsc::make_test();
193         auto w = sc.create_worker();
194         const rxsc::test::messages<int> on;
195 
196         std::runtime_error ex("scope on_error from source");
197 
198         int resource_factory_invoked = 0;
199         int observable_factory_invoked = 0;
200 
201         rxu::detail::maybe<rx::test::testable_observable<int>> xs;
202 
203         typedef rx::resource<int> resource;
204 
205         WHEN("created by scope"){
206 
207             auto res = w.start(
__anonbc61a3d20c02() 208                 [&]() {
209                     return rx::observable<>::
210                         scope(
211                             [&](){
212                                 ++resource_factory_invoked;
213                                 return resource(sc.clock());
214                             },
215                             [&](resource r){
216                                 ++observable_factory_invoked;
217                                 xs.reset(sc.make_cold_observable(rxu::to_vector({
218                                     on.next(100, r.get()),
219                                     on.error(200, ex)
220                                 })));
221                                 return xs.get();
222                             }
223                         )
224                         // forget type to workaround lambda deduction bug on msvc 2013
225                         .as_dynamic();
226                 }
227             );
228 
229             THEN("Resource factory is used once"){
230                 REQUIRE(1 == resource_factory_invoked);
231             }
232 
233             THEN("Observable factory is used once"){
234                 REQUIRE(1 == observable_factory_invoked);
235             }
236 
237             THEN("the output stops on error"){
238                 auto required = rxu::to_vector({
239                     on.next(300, 200),
240                     on.error(400, ex)
241                 });
242                 auto actual = res.get_observer().messages();
243                 REQUIRE(required == actual);
244             }
245 
246             THEN("there was one subscription and one unsubscription"){
247                 auto required = rxu::to_vector({
248                     on.subscribe(200, 400)
249                 });
250                 auto actual = xs.get().subscriptions();
251                 REQUIRE(required == actual);
252             }
253         }
254     }
255 }
256 
257 SCENARIO("scope, dispose", "[scope][sources]"){
258     GIVEN("a test cold observable of ints"){
259         auto sc = rxsc::make_test();
260         auto w = sc.create_worker();
261         const rxsc::test::messages<int> on;
262 
263         int resource_factory_invoked = 0;
264         int observable_factory_invoked = 0;
265 
266         rxu::detail::maybe<rx::test::testable_observable<int>> xs;
267 
268         typedef rx::resource<int> resource;
269 
270         WHEN("created by scope"){
271 
272             auto res = w.start(
__anonbc61a3d20f02() 273                 [&]() {
274                     return rx::observable<>::
275                         scope(
276                             [&](){
277                                 ++resource_factory_invoked;
278                                 return resource(sc.clock());
279                             },
280                             [&](resource r){
281                                 ++observable_factory_invoked;
282                                 xs.reset(sc.make_cold_observable(rxu::to_vector({
283                                     on.next(100, r.get()),
284                                     on.next(1000, r.get() + 1)
285                                 })));
286                                 return xs.get();
287                             }
288                         )
289                         // forget type to workaround lambda deduction bug on msvc 2013
290                         .as_dynamic();
291                 }
292             );
293 
294             THEN("Resource factory is used once"){
295                 REQUIRE(1 == resource_factory_invoked);
296             }
297 
298             THEN("Observable factory is used once"){
299                 REQUIRE(1 == observable_factory_invoked);
300             }
301 
302             THEN("the output contains resulting ints"){
303                 auto required = rxu::to_vector({
304                     on.next(300, 200)
305                 });
306                 auto actual = res.get_observer().messages();
307                 REQUIRE(required == actual);
308             }
309 
310             THEN("there was one subscription and one unsubscription"){
311                 auto required = rxu::to_vector({
312                     on.subscribe(200, 1000)
313                 });
314                 auto actual = xs.get().subscriptions();
315                 REQUIRE(required == actual);
316             }
317         }
318     }
319 }
320 
321 SCENARIO("scope, throw resource selector", "[scope][sources][!throws]"){
322     GIVEN("a test cold observable of ints"){
323         auto sc = rxsc::make_test();
324         auto w = sc.create_worker();
325         const rxsc::test::messages<int> on;
326 
327         std::runtime_error ex("scope on_error from source");
328 
329         int resource_factory_invoked = 0;
330         int observable_factory_invoked = 0;
331 
332         typedef rx::resource<int> resource;
333 
334         WHEN("created by scope"){
335 
336             auto res = w.start(
__anonbc61a3d21202() 337                 [&]() {
338                     return rx::observable<>::
339                         scope(
340                             [&]() -> resource {
341                                 ++resource_factory_invoked;
342                                 rxu::throw_exception(ex);
343                                 //return resource(sc.clock());
344                             },
345                             [&](resource){
346                                 ++observable_factory_invoked;
347                                 return rx::observable<>::never<int>();
348                             }
349                         )
350                         // forget type to workaround lambda deduction bug on msvc 2013
351                         .as_dynamic();
352                     }
353             );
354 
355             THEN("Resource factory is used once"){
356                 REQUIRE(1 == resource_factory_invoked);
357             }
358 
359             THEN("Observable factory is not used"){
360                 REQUIRE(0 == observable_factory_invoked);
361             }
362 
363             THEN("the output stops on error"){
364                 auto required = rxu::to_vector({
365                     on.error(200, ex)
366                 });
367                 auto actual = res.get_observer().messages();
368                 REQUIRE(required == actual);
369             }
370         }
371     }
372 }
373 
374 SCENARIO("scope, throw resource usage", "[scope][sources][!throws]"){
375     GIVEN("a test cold observable of ints"){
376         auto sc = rxsc::make_test();
377         auto w = sc.create_worker();
378         const rxsc::test::messages<int> on;
379 
380         std::runtime_error ex("scope on_error from source");
381 
382         int resource_factory_invoked = 0;
383         int observable_factory_invoked = 0;
384 
385         typedef rx::resource<int> resource;
386 
387         WHEN("created by scope"){
388 
389             auto res = w.start(
__anonbc61a3d21502() 390                 [&]() {
391                     return rx::observable<>::
392                         scope(
393                             [&](){
394                                 ++resource_factory_invoked;
395                                 return resource(sc.clock());
396                             },
397                             [&](resource) -> rx::observable<int> {
398                                 ++observable_factory_invoked;
399                                 rxu::throw_exception(ex);
400                             }
401                         )
402                         // forget type to workaround lambda deduction bug on msvc 2013
403                         .as_dynamic();
404                     }
405             );
406 
407             THEN("Resource factory is used once"){
408                 REQUIRE(1 == resource_factory_invoked);
409             }
410 
411             THEN("Observable factory is used once"){
412                 REQUIRE(1 == observable_factory_invoked);
413             }
414 
415             THEN("the output stops on error"){
416                 auto required = rxu::to_vector({
417                     on.error(200, ex)
418                 });
419                 auto actual = res.get_observer().messages();
420                 REQUIRE(required == actual);
421             }
422         }
423     }
424 }
425