SampleTest.cs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606
  1. // Licensed to the .NET Foundation under one or more agreements.
  2. // The .NET Foundation licenses this file to you under the Apache 2.0 License.
  3. // See the LICENSE file in the project root for more information.
  4. using System;
  5. using System.Linq;
  6. using System.Reactive.Concurrency;
  7. using System.Reactive.Linq;
  8. using Microsoft.Reactive.Testing;
  9. using Xunit;
  10. namespace ReactiveTests.Tests
  11. {
  12. public class SampleTest : ReactiveTest
  13. {
  14. [Fact]
  15. public void Sample_ArgumentChecking()
  16. {
  17. var scheduler = new TestScheduler();
  18. var someObservable = Observable.Empty<int>();
  19. ReactiveAssert.Throws<ArgumentNullException>(() => Observable.Sample(default(IObservable<int>), TimeSpan.Zero));
  20. ReactiveAssert.Throws<ArgumentNullException>(() => Observable.Sample(default(IObservable<int>), TimeSpan.Zero, scheduler));
  21. ReactiveAssert.Throws<ArgumentNullException>(() => Observable.Sample(someObservable, TimeSpan.Zero, null));
  22. ReactiveAssert.Throws<ArgumentOutOfRangeException>(() => Observable.Sample(someObservable, TimeSpan.FromSeconds(-1)));
  23. ReactiveAssert.Throws<ArgumentOutOfRangeException>(() => Observable.Sample(someObservable, TimeSpan.FromSeconds(-1), scheduler));
  24. ReactiveAssert.Throws<ArgumentNullException>(() => Observable.Sample(default(IObservable<int>), someObservable));
  25. ReactiveAssert.Throws<ArgumentNullException>(() => Observable.Sample(someObservable, default(IObservable<int>)));
  26. }
  27. [Fact]
  28. public void Sample_Regular()
  29. {
  30. var scheduler = new TestScheduler();
  31. var xs = scheduler.CreateHotObservable(
  32. OnNext(150, 1),
  33. OnNext(210, 2),
  34. OnNext(230, 3),
  35. OnNext(260, 4),
  36. OnNext(300, 5),
  37. OnNext(350, 6),
  38. OnNext(380, 7),
  39. OnCompleted<int>(390)
  40. );
  41. var res = scheduler.Start(() =>
  42. xs.Sample(TimeSpan.FromTicks(50), scheduler)
  43. );
  44. res.Messages.AssertEqual(
  45. OnNext(250, 3),
  46. OnNext(300, 5), /* CHECK: boundary of sampling */
  47. OnNext(350, 6),
  48. OnNext(400, 7), /* Sample in last bucket */
  49. OnCompleted<int>(400)
  50. );
  51. xs.Subscriptions.AssertEqual(
  52. Subscribe(200, 390)
  53. );
  54. }
  55. [Fact]
  56. public void Sample_Periodic_Regular()
  57. {
  58. var scheduler = new PeriodicTestScheduler();
  59. var xs = scheduler.CreateHotObservable(
  60. OnNext(150, 1),
  61. OnNext(210, 2),
  62. OnNext(230, 3),
  63. OnNext(260, 4),
  64. OnNext(300, 5),
  65. OnNext(350, 6),
  66. OnNext(380, 7),
  67. OnCompleted<int>(390)
  68. );
  69. var res = scheduler.Start(() =>
  70. xs.Sample(TimeSpan.FromTicks(50), scheduler)
  71. );
  72. res.Messages.AssertEqual(
  73. OnNext(250, 3),
  74. OnNext(300, 5), /* CHECK: boundary of sampling */
  75. OnNext(350, 6),
  76. OnNext(400, 7), /* Sample in last bucket */
  77. OnCompleted<int>(400)
  78. );
  79. xs.Subscriptions.AssertEqual(
  80. Subscribe(200, 390)
  81. );
  82. #if !WINDOWS
  83. scheduler.Timers.AssertEqual(
  84. new TimerRun(200, 400) { 250, 300, 350, 400 }
  85. );
  86. #endif
  87. }
  88. [Fact]
  89. public void Sample_ErrorInFlight()
  90. {
  91. var scheduler = new TestScheduler();
  92. var ex = new Exception();
  93. var xs = scheduler.CreateHotObservable(
  94. OnNext(150, 1),
  95. OnNext(210, 2),
  96. OnNext(230, 3),
  97. OnNext(260, 4),
  98. OnNext(300, 5),
  99. OnNext(310, 6),
  100. OnError<int>(330, ex)
  101. );
  102. var res = scheduler.Start(() =>
  103. xs.Sample(TimeSpan.FromTicks(50), scheduler)
  104. );
  105. res.Messages.AssertEqual(
  106. OnNext(250, 3),
  107. OnNext(300, 5), /* CHECK: boundary of sampling */
  108. OnError<int>(330, ex)
  109. );
  110. xs.Subscriptions.AssertEqual(
  111. Subscribe(200, 330)
  112. );
  113. }
  114. [Fact]
  115. public void Sample_Periodic_ErrorInFlight()
  116. {
  117. var scheduler = new PeriodicTestScheduler();
  118. var ex = new Exception();
  119. var xs = scheduler.CreateHotObservable(
  120. OnNext(150, 1),
  121. OnNext(210, 2),
  122. OnNext(230, 3),
  123. OnNext(260, 4),
  124. OnNext(300, 5),
  125. OnNext(310, 6),
  126. OnError<int>(330, ex)
  127. );
  128. var res = scheduler.Start(() =>
  129. xs.Sample(TimeSpan.FromTicks(50), scheduler)
  130. );
  131. res.Messages.AssertEqual(
  132. OnNext(250, 3),
  133. OnNext(300, 5), /* CHECK: boundary of sampling */
  134. OnError<int>(330, ex)
  135. );
  136. xs.Subscriptions.AssertEqual(
  137. Subscribe(200, 330)
  138. );
  139. #if !WINDOWS
  140. scheduler.Timers.AssertEqual(
  141. new TimerRun(200, 330) { 250, 300 }
  142. );
  143. #endif
  144. }
  145. [Fact]
  146. public void Sample_Empty()
  147. {
  148. var scheduler = new TestScheduler();
  149. var xs = scheduler.CreateHotObservable(
  150. OnNext(150, 1),
  151. OnCompleted<int>(300)
  152. );
  153. var res = scheduler.Start(() =>
  154. xs.Sample(TimeSpan.FromTicks(50), scheduler)
  155. );
  156. res.Messages.AssertEqual(
  157. OnCompleted<int>(300)
  158. );
  159. xs.Subscriptions.AssertEqual(
  160. Subscribe(200, 300)
  161. );
  162. }
  163. [Fact]
  164. public void Sample_Periodic_Empty()
  165. {
  166. var scheduler = new PeriodicTestScheduler();
  167. var xs = scheduler.CreateHotObservable(
  168. OnNext(150, 1),
  169. OnCompleted<int>(300)
  170. );
  171. var res = scheduler.Start(() =>
  172. xs.Sample(TimeSpan.FromTicks(50), scheduler)
  173. );
  174. res.Messages.AssertEqual(
  175. OnCompleted<int>(300)
  176. );
  177. xs.Subscriptions.AssertEqual(
  178. Subscribe(200, 300)
  179. );
  180. #if !WINDOWS
  181. scheduler.Timers.AssertEqual(
  182. new TimerRun(200, 300) { 250, 300 }
  183. );
  184. #endif
  185. }
  186. [Fact]
  187. public void Sample_Error()
  188. {
  189. var scheduler = new TestScheduler();
  190. var ex = new Exception();
  191. var xs = scheduler.CreateHotObservable(
  192. OnNext(150, 1),
  193. OnError<int>(300, ex)
  194. );
  195. var res = scheduler.Start(() =>
  196. xs.Sample(TimeSpan.FromTicks(50), scheduler)
  197. );
  198. res.Messages.AssertEqual(
  199. OnError<int>(300, ex)
  200. );
  201. xs.Subscriptions.AssertEqual(
  202. Subscribe(200, 300)
  203. );
  204. }
  205. [Fact]
  206. public void Sample_Periodic_Error()
  207. {
  208. var scheduler = new PeriodicTestScheduler();
  209. var ex = new Exception();
  210. var xs = scheduler.CreateHotObservable(
  211. OnNext(150, 1),
  212. OnError<int>(300, ex)
  213. );
  214. var res = scheduler.Start(() =>
  215. xs.Sample(TimeSpan.FromTicks(50), scheduler)
  216. );
  217. res.Messages.AssertEqual(
  218. OnError<int>(300, ex)
  219. );
  220. xs.Subscriptions.AssertEqual(
  221. Subscribe(200, 300)
  222. );
  223. #if !WINDOWS
  224. scheduler.Timers.AssertEqual(
  225. new TimerRun(200, 300) { 250 }
  226. );
  227. #endif
  228. }
  229. [Fact]
  230. public void Sample_Never()
  231. {
  232. var scheduler = new TestScheduler();
  233. var xs = scheduler.CreateHotObservable(
  234. OnNext(150, 1)
  235. );
  236. var res = scheduler.Start(() =>
  237. xs.Sample(TimeSpan.FromTicks(50), scheduler)
  238. );
  239. res.Messages.AssertEqual(
  240. );
  241. xs.Subscriptions.AssertEqual(
  242. Subscribe(200, 1000)
  243. );
  244. }
  245. [Fact]
  246. public void Sample_Periodic_Never()
  247. {
  248. var scheduler = new PeriodicTestScheduler();
  249. var xs = scheduler.CreateHotObservable(
  250. OnNext(150, 1)
  251. );
  252. var res = scheduler.Start(() =>
  253. xs.Sample(TimeSpan.FromTicks(50), scheduler)
  254. );
  255. res.Messages.AssertEqual(
  256. );
  257. xs.Subscriptions.AssertEqual(
  258. Subscribe(200, 1000)
  259. );
  260. #if !WINDOWS
  261. scheduler.Timers.AssertEqual(
  262. new TimerRun(200, 1000) { 250, 300, 350, 400, 450, 500, 550, 600, 650, 700, 750, 800, 850, 900, 950 }
  263. );
  264. #endif
  265. }
  266. [Fact]
  267. public void Sample_DefaultScheduler_Periodic()
  268. {
  269. var res = Observable.Return(42).Sample(TimeSpan.FromMilliseconds(1)).ToEnumerable().Single();
  270. Assert.Equal(42, res);
  271. }
  272. [Fact]
  273. public void Sample_DefaultScheduler_PeriodicDisabled()
  274. {
  275. var res = Observable.Return(42).Sample(TimeSpan.FromMilliseconds(1), Scheduler.Default.DisableOptimizations()).ToEnumerable().Single();
  276. Assert.Equal(42, res);
  277. }
  278. [Fact]
  279. public void Sample_Sampler_Simple1()
  280. {
  281. var scheduler = new TestScheduler();
  282. var xs = scheduler.CreateHotObservable(
  283. OnNext(150, 1),
  284. OnNext(220, 2),
  285. OnNext(240, 3),
  286. OnNext(290, 4),
  287. OnNext(300, 5),
  288. OnNext(310, 6),
  289. OnCompleted<int>(400)
  290. );
  291. var ys = scheduler.CreateHotObservable(
  292. OnNext(150, ""),
  293. OnNext(210, "bar"),
  294. OnNext(250, "foo"),
  295. OnNext(260, "qux"),
  296. OnNext(320, "baz"),
  297. OnCompleted<string>(500)
  298. );
  299. var res = scheduler.Start(() =>
  300. xs.Sample(ys)
  301. );
  302. res.Messages.AssertEqual(
  303. OnNext(250, 3),
  304. OnNext(320, 6),
  305. OnCompleted<int>(500 /* on sampling boundaries only */)
  306. );
  307. xs.Subscriptions.AssertEqual(
  308. Subscribe(200, 400)
  309. );
  310. ys.Subscriptions.AssertEqual(
  311. Subscribe(200, 500)
  312. );
  313. }
  314. [Fact]
  315. public void Sample_Sampler_Simple2()
  316. {
  317. var scheduler = new TestScheduler();
  318. var xs = scheduler.CreateHotObservable(
  319. OnNext(150, 1),
  320. OnNext(220, 2),
  321. OnNext(240, 3),
  322. OnNext(290, 4),
  323. OnNext(300, 5),
  324. OnNext(310, 6),
  325. OnNext(360, 7),
  326. OnCompleted<int>(400)
  327. );
  328. var ys = scheduler.CreateHotObservable(
  329. OnNext(150, ""),
  330. OnNext(210, "bar"),
  331. OnNext(250, "foo"),
  332. OnNext(260, "qux"),
  333. OnNext(320, "baz"),
  334. OnCompleted<string>(500)
  335. );
  336. var res = scheduler.Start(() =>
  337. xs.Sample(ys)
  338. );
  339. res.Messages.AssertEqual(
  340. OnNext(250, 3),
  341. OnNext(320, 6),
  342. OnNext(500, 7),
  343. OnCompleted<int>(500 /* on sampling boundaries only */)
  344. );
  345. xs.Subscriptions.AssertEqual(
  346. Subscribe(200, 400)
  347. );
  348. ys.Subscriptions.AssertEqual(
  349. Subscribe(200, 500)
  350. );
  351. }
  352. [Fact]
  353. public void Sample_Sampler_Simple3()
  354. {
  355. var scheduler = new TestScheduler();
  356. var xs = scheduler.CreateHotObservable(
  357. OnNext(150, 1),
  358. OnNext(220, 2),
  359. OnNext(240, 3),
  360. OnNext(290, 4),
  361. OnCompleted<int>(300)
  362. );
  363. var ys = scheduler.CreateHotObservable(
  364. OnNext(150, ""),
  365. OnNext(210, "bar"),
  366. OnNext(250, "foo"),
  367. OnNext(260, "qux"),
  368. OnNext(320, "baz"),
  369. OnCompleted<string>(500)
  370. );
  371. var res = scheduler.Start(() =>
  372. xs.Sample(ys)
  373. );
  374. res.Messages.AssertEqual(
  375. OnNext(250, 3),
  376. OnNext(320, 4),
  377. OnCompleted<int>(320 /* on sampling boundaries only */)
  378. );
  379. xs.Subscriptions.AssertEqual(
  380. Subscribe(200, 300)
  381. );
  382. ys.Subscriptions.AssertEqual(
  383. Subscribe(200, 320)
  384. );
  385. }
  386. [Fact]
  387. public void Sample_Sampler_completes_first()
  388. {
  389. var scheduler = new TestScheduler();
  390. var xs = scheduler.CreateHotObservable(
  391. OnNext(150, 1),
  392. OnNext(220, 2),
  393. OnNext(240, 3),
  394. OnNext(290, 4),
  395. OnCompleted<int>(600)
  396. );
  397. var ys = scheduler.CreateHotObservable(
  398. OnNext(150, ""),
  399. OnNext(210, "bar"),
  400. OnNext(250, "foo"),
  401. OnNext(260, "qux"),
  402. OnNext(320, "baz"),
  403. OnCompleted<string>(500)
  404. );
  405. var res = scheduler.Start(() =>
  406. xs.Sample(ys)
  407. );
  408. res.Messages.AssertEqual(
  409. OnNext(250, 3),
  410. OnNext(320, 4),
  411. OnCompleted<int>(600 /* on sampling boundaries only */)
  412. );
  413. xs.Subscriptions.AssertEqual(
  414. Subscribe(200, 600)
  415. );
  416. ys.Subscriptions.AssertEqual(
  417. Subscribe(200, 500)
  418. );
  419. }
  420. [Fact]
  421. public void Sample_Sampler_SourceThrows()
  422. {
  423. var ex = new Exception();
  424. var scheduler = new TestScheduler();
  425. var xs = scheduler.CreateHotObservable(
  426. OnNext(150, 1),
  427. OnNext(220, 2),
  428. OnNext(240, 3),
  429. OnNext(290, 4),
  430. OnNext(300, 5),
  431. OnNext(310, 6),
  432. OnError<int>(320, ex)
  433. );
  434. var ys = scheduler.CreateHotObservable(
  435. OnNext(150, ""),
  436. OnNext(210, "bar"),
  437. OnNext(250, "foo"),
  438. OnNext(260, "qux"),
  439. OnNext(330, "baz"),
  440. OnCompleted<string>(400)
  441. );
  442. var res = scheduler.Start(() =>
  443. xs.Sample(ys)
  444. );
  445. res.Messages.AssertEqual(
  446. OnNext(250, 3),
  447. OnError<int>(320, ex)
  448. );
  449. xs.Subscriptions.AssertEqual(
  450. Subscribe(200, 320)
  451. );
  452. ys.Subscriptions.AssertEqual(
  453. Subscribe(200, 320)
  454. );
  455. }
  456. #if !NO_PERF // BREAKING CHANGE v2 > v1.x - behavior when sampler throws
  457. [Fact]
  458. public void Sample_Sampler_SamplerThrows()
  459. {
  460. var ex = new Exception();
  461. var scheduler = new TestScheduler();
  462. var xs = scheduler.CreateHotObservable(
  463. OnNext(150, 1),
  464. OnNext(220, 2),
  465. OnNext(240, 3),
  466. OnNext(290, 4),
  467. OnNext(300, 5),
  468. OnNext(310, 6),
  469. OnCompleted<int>(400)
  470. );
  471. var ys = scheduler.CreateHotObservable(
  472. OnNext(150, ""),
  473. OnNext(210, "bar"),
  474. OnNext(250, "foo"),
  475. OnNext(260, "qux"),
  476. OnError<string>(320, ex)
  477. );
  478. var res = scheduler.Start(() =>
  479. xs.Sample(ys)
  480. );
  481. res.Messages.AssertEqual(
  482. OnNext(250, 3),
  483. OnError<int>(320, ex)
  484. );
  485. xs.Subscriptions.AssertEqual(
  486. Subscribe(200, 320)
  487. );
  488. ys.Subscriptions.AssertEqual(
  489. Subscribe(200, 320)
  490. );
  491. }
  492. #endif
  493. }
  494. }