Home | History | Annotate | Download | only in sources
      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(
     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(
     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(
    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(
    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(
    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(
    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(
    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