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( __anon0a7a75b00102() 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( __anon0a7a75b00502() 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( __anon0a7a75b00902() 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( __anon0a7a75b00c02() 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( __anon0a7a75b00f02() 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( __anon0a7a75b01202() 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( __anon0a7a75b01502() 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