GenerateTest.cs 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497
  1. // Licensed to the .NET Foundation under one or more agreements.
  2. // The .NET Foundation licenses this file to you under the MIT License.
  3. // See the LICENSE file in the project root for more information.
  4. using System;
  5. using System.Collections.Generic;
  6. using System.Linq;
  7. using System.Reactive.Concurrency;
  8. using System.Reactive.Linq;
  9. using System.Runtime.CompilerServices;
  10. using System.Threading;
  11. using System.Threading.Tasks;
  12. using Microsoft.Reactive.Testing;
  13. using ReactiveTests.Dummies;
  14. using Microsoft.VisualStudio.TestTools.UnitTesting;
  15. using Assert = Xunit.Assert;
  16. namespace ReactiveTests.Tests
  17. {
  18. [TestClass]
  19. public class GenerateTest : ReactiveTest
  20. {
  21. #region + Non-timed +
  22. [TestMethod]
  23. public void Generate_ArgumentChecking()
  24. {
  25. ReactiveAssert.Throws<ArgumentNullException>(() => Observable.Generate(0, DummyFunc<int, bool>.Instance, DummyFunc<int, int>.Instance, DummyFunc<int, int>.Instance, (IScheduler)null));
  26. ReactiveAssert.Throws<ArgumentNullException>(() => Observable.Generate(0, null, DummyFunc<int, int>.Instance, DummyFunc<int, int>.Instance, DummyScheduler.Instance));
  27. ReactiveAssert.Throws<ArgumentNullException>(() => Observable.Generate(0, DummyFunc<int, bool>.Instance, DummyFunc<int, int>.Instance, (Func<int, int>)null, DummyScheduler.Instance));
  28. ReactiveAssert.Throws<ArgumentNullException>(() => Observable.Generate(0, DummyFunc<int, bool>.Instance, null, DummyFunc<int, int>.Instance, DummyScheduler.Instance));
  29. ReactiveAssert.Throws<ArgumentNullException>(() => Observable.Generate(0, DummyFunc<int, bool>.Instance, DummyFunc<int, int>.Instance, DummyFunc<int, int>.Instance, DummyScheduler.Instance).Subscribe(null));
  30. }
  31. [TestMethod]
  32. public void Generate_Finite()
  33. {
  34. var scheduler = new TestScheduler();
  35. var res = scheduler.Start(() =>
  36. Observable.Generate(0, x => x <= 3, x => x + 1, x => x, scheduler)
  37. );
  38. res.Messages.AssertEqual(
  39. OnNext(201, 0),
  40. OnNext(202, 1),
  41. OnNext(203, 2),
  42. OnNext(204, 3),
  43. OnCompleted<int>(205)
  44. );
  45. }
  46. [TestMethod]
  47. public void Generate_Throw_Condition()
  48. {
  49. var scheduler = new TestScheduler();
  50. var ex = new Exception();
  51. var res = scheduler.Start(() =>
  52. Observable.Generate(0, new Func<int, bool>(x => { throw ex; }), x => x + 1, x => x, scheduler)
  53. );
  54. res.Messages.AssertEqual(
  55. OnError<int>(201, ex)
  56. );
  57. }
  58. [TestMethod]
  59. public void Generate_Throw_ResultSelector()
  60. {
  61. var scheduler = new TestScheduler();
  62. var ex = new Exception();
  63. var res = scheduler.Start(() =>
  64. Observable.Generate(0, x => true, x => x + 1, new Func<int, int>(x => { throw ex; }), scheduler)
  65. );
  66. res.Messages.AssertEqual(
  67. OnError<int>(201, ex)
  68. );
  69. }
  70. [TestMethod]
  71. public void Generate_Throw_Iterate()
  72. {
  73. var scheduler = new TestScheduler();
  74. var ex = new Exception();
  75. var res = scheduler.Start(() =>
  76. Observable.Generate(0, x => true, new Func<int, int>(x => { throw ex; }), x => x, scheduler)
  77. );
  78. res.Messages.AssertEqual(
  79. OnNext(201, 0),
  80. OnError<int>(202, ex)
  81. );
  82. }
  83. [TestMethod]
  84. public void Generate_Dispose()
  85. {
  86. var scheduler = new TestScheduler();
  87. var res = scheduler.Start(() =>
  88. Observable.Generate(0, x => true, x => x + 1, x => x, scheduler),
  89. 203
  90. );
  91. res.Messages.AssertEqual(
  92. OnNext(201, 0),
  93. OnNext(202, 1)
  94. );
  95. }
  96. [TestMethod]
  97. public void Generate_DefaultScheduler_ArgumentChecking()
  98. {
  99. ReactiveAssert.Throws<ArgumentNullException>(() => Observable.Generate(0, null, DummyFunc<int, int>.Instance, DummyFunc<int, int>.Instance));
  100. ReactiveAssert.Throws<ArgumentNullException>(() => Observable.Generate(0, DummyFunc<int, bool>.Instance, DummyFunc<int, int>.Instance, (Func<int, int>)null));
  101. ReactiveAssert.Throws<ArgumentNullException>(() => Observable.Generate(0, DummyFunc<int, bool>.Instance, null, DummyFunc<int, int>.Instance));
  102. ReactiveAssert.Throws<ArgumentNullException>(() => Observable.Generate(0, DummyFunc<int, bool>.Instance, DummyFunc<int, int>.Instance, DummyFunc<int, int>.Instance).Subscribe(null));
  103. }
  104. [TestMethod]
  105. public void Generate_DefaultScheduler()
  106. {
  107. Observable.Generate(0, x => x < 10, x => x + 1, x => x).AssertEqual(Observable.Generate(0, x => x < 10, x => x + 1, x => x, DefaultScheduler.Instance));
  108. }
  109. #if !NO_PERF
  110. [TestMethod]
  111. public void Generate_LongRunning1()
  112. {
  113. var start = default(ManualResetEvent);
  114. var end = default(ManualResetEvent);
  115. var s = new TestLongRunningScheduler(x => start = x, x => end = x);
  116. var xs = Observable.Generate(0, x => x < 100, x => x + 1, x => x, s);
  117. var lst = new List<int>();
  118. var done = false;
  119. xs.Subscribe(x => { lst.Add(x); }, () => done = true);
  120. end.WaitOne();
  121. Assert.True(lst.SequenceEqual(Enumerable.Range(0, 100)));
  122. Assert.True(done);
  123. }
  124. [TestMethod]
  125. [MethodImpl(MethodImplOptions.NoOptimization)]
  126. public void Generate_LongRunning2()
  127. {
  128. var start = default(ManualResetEvent);
  129. var end = default(ManualResetEvent);
  130. var s = new TestLongRunningScheduler(x => start = x, x => end = x);
  131. var xs = Observable.Generate(0, _ => true, x => x + 1, x => x, s);
  132. var lst = new List<int>();
  133. var d = xs.Subscribe(x => { lst.Add(x); });
  134. start.WaitOne();
  135. while (lst.Count < 100)
  136. {
  137. ;
  138. }
  139. d.Dispose();
  140. end.WaitOne();
  141. Assert.True(lst.Take(100).SequenceEqual(Enumerable.Range(0, 100)));
  142. }
  143. [TestMethod]
  144. public void Generate_LongRunning_Throw()
  145. {
  146. var start = default(ManualResetEvent);
  147. var end = default(ManualResetEvent);
  148. var s = new TestLongRunningScheduler(x => start = x, x => end = x);
  149. var ex = new Exception();
  150. var xs = Observable.Generate(0, x => { if (x < 100) { return true; } throw ex; }, x => x + 1, x => x, s);
  151. var lst = new List<int>();
  152. var e = default(Exception);
  153. var done = false;
  154. xs.Subscribe(x => { lst.Add(x); }, e_ => e = e_, () => done = true);
  155. end.WaitOne();
  156. Assert.True(lst.SequenceEqual(Enumerable.Range(0, 100)));
  157. Assert.Same(ex, e);
  158. Assert.False(done);
  159. }
  160. #endif
  161. #endregion
  162. #region + Timed +
  163. [TestMethod]
  164. public void Generate_TimeSpan_ArgumentChecking()
  165. {
  166. ReactiveAssert.Throws<ArgumentNullException>(() => Observable.Generate(0, DummyFunc<int, bool>.Instance, DummyFunc<int, int>.Instance, DummyFunc<int, int>.Instance, DummyFunc<int, TimeSpan>.Instance, null));
  167. ReactiveAssert.Throws<ArgumentNullException>(() => Observable.Generate(0, null, DummyFunc<int, int>.Instance, DummyFunc<int, int>.Instance, DummyFunc<int, TimeSpan>.Instance, DummyScheduler.Instance));
  168. ReactiveAssert.Throws<ArgumentNullException>(() => Observable.Generate(0, DummyFunc<int, bool>.Instance, DummyFunc<int, int>.Instance, (Func<int, int>)null, DummyFunc<int, TimeSpan>.Instance, DummyScheduler.Instance));
  169. ReactiveAssert.Throws<ArgumentNullException>(() => Observable.Generate(0, DummyFunc<int, bool>.Instance, null, DummyFunc<int, int>.Instance, DummyFunc<int, TimeSpan>.Instance, DummyScheduler.Instance));
  170. ReactiveAssert.Throws<ArgumentNullException>(() => Observable.Generate(0, DummyFunc<int, bool>.Instance, DummyFunc<int, int>.Instance, DummyFunc<int, int>.Instance, (Func<int, TimeSpan>)null, DummyScheduler.Instance));
  171. ReactiveAssert.Throws<ArgumentNullException>(() => Observable.Generate(0, DummyFunc<int, bool>.Instance, DummyFunc<int, int>.Instance, DummyFunc<int, int>.Instance, DummyFunc<int, TimeSpan>.Instance, DummyScheduler.Instance).Subscribe(null));
  172. }
  173. [TestMethod]
  174. public void Generate_TimeSpan_Finite()
  175. {
  176. var scheduler = new TestScheduler();
  177. var res = scheduler.Start(() =>
  178. Observable.Generate(0, x => x <= 3, x => x + 1, x => x, x => TimeSpan.FromTicks(x + 1), scheduler)
  179. );
  180. res.Messages.AssertEqual(
  181. OnNext(202, 0),
  182. OnNext(204, 1),
  183. OnNext(207, 2),
  184. OnNext(211, 3),
  185. OnCompleted<int>(211)
  186. );
  187. }
  188. [TestMethod]
  189. public void Generate_TimeSpan_Throw_Condition()
  190. {
  191. var scheduler = new TestScheduler();
  192. var ex = new Exception();
  193. var res = scheduler.Start(() =>
  194. Observable.Generate(0, new Func<int, bool>(x => { throw ex; }), x => x + 1, x => x, x => TimeSpan.FromTicks(x + 1), scheduler)
  195. );
  196. res.Messages.AssertEqual(
  197. OnError<int>(201, ex)
  198. );
  199. }
  200. [TestMethod]
  201. public void Generate_TimeSpan_Throw_ResultSelector()
  202. {
  203. var scheduler = new TestScheduler();
  204. var ex = new Exception();
  205. var res = scheduler.Start(() =>
  206. Observable.Generate(0, x => true, x => x + 1, new Func<int, int>(x => { throw ex; }), x => TimeSpan.FromTicks(x + 1), scheduler)
  207. );
  208. res.Messages.AssertEqual(
  209. OnError<int>(201, ex)
  210. );
  211. }
  212. [TestMethod]
  213. public void Generate_TimeSpan_Throw_Iterate()
  214. {
  215. var scheduler = new TestScheduler();
  216. var ex = new Exception();
  217. var res = scheduler.Start(() =>
  218. Observable.Generate(0, x => true, new Func<int, int>(x => { throw ex; }), x => x, x => TimeSpan.FromTicks(x + 1), scheduler)
  219. );
  220. res.Messages.AssertEqual(
  221. OnNext(202, 0),
  222. OnError<int>(202, ex)
  223. );
  224. }
  225. [TestMethod]
  226. public void Generate_TimeSpan_Throw_TimeSelector()
  227. {
  228. var scheduler = new TestScheduler();
  229. var ex = new Exception();
  230. var res = scheduler.Start(() =>
  231. Observable.Generate(0, x => true, x => x + 1, x => x, new Func<int, TimeSpan>(x => { throw ex; }), scheduler)
  232. );
  233. res.Messages.AssertEqual(
  234. OnError<int>(201, ex)
  235. );
  236. }
  237. [TestMethod]
  238. public void Generate_TimeSpan_Dispose()
  239. {
  240. var scheduler = new TestScheduler();
  241. var res = scheduler.Start(() =>
  242. Observable.Generate(0, x => true, x => x + 1, x => x, x => TimeSpan.FromTicks(x + 1), scheduler),
  243. 210
  244. );
  245. res.Messages.AssertEqual(
  246. OnNext(202, 0),
  247. OnNext(204, 1),
  248. OnNext(207, 2)
  249. );
  250. }
  251. [TestMethod]
  252. public void Generate_TimeSpan_DefaultScheduler_ArgumentChecking()
  253. {
  254. ReactiveAssert.Throws<ArgumentNullException>(() => Observable.Generate(0, null, DummyFunc<int, int>.Instance, DummyFunc<int, int>.Instance, DummyFunc<int, TimeSpan>.Instance));
  255. ReactiveAssert.Throws<ArgumentNullException>(() => Observable.Generate(0, DummyFunc<int, bool>.Instance, DummyFunc<int, int>.Instance, (Func<int, int>)null, DummyFunc<int, TimeSpan>.Instance));
  256. ReactiveAssert.Throws<ArgumentNullException>(() => Observable.Generate(0, DummyFunc<int, bool>.Instance, null, DummyFunc<int, int>.Instance, DummyFunc<int, TimeSpan>.Instance));
  257. ReactiveAssert.Throws<ArgumentNullException>(() => Observable.Generate(0, DummyFunc<int, bool>.Instance, DummyFunc<int, int>.Instance, DummyFunc<int, int>.Instance, (Func<int, TimeSpan>)null));
  258. ReactiveAssert.Throws<ArgumentNullException>(() => Observable.Generate(0, DummyFunc<int, bool>.Instance, DummyFunc<int, int>.Instance, DummyFunc<int, int>.Instance, DummyFunc<int, TimeSpan>.Instance).Subscribe(null));
  259. }
  260. [TestMethod]
  261. public void Generate_TimeSpan_DefaultScheduler()
  262. {
  263. Observable.Generate(0, x => x < 10, x => x + 1, x => x, x => TimeSpan.FromMilliseconds(x)).AssertEqual(Observable.Generate(0, x => x < 10, x => x + 1, x => x, x => TimeSpan.FromMilliseconds(x), DefaultScheduler.Instance));
  264. }
  265. [TestMethod]
  266. public void Generate_DateTimeOffset_ArgumentChecking()
  267. {
  268. ReactiveAssert.Throws<ArgumentNullException>(() => Observable.Generate(0, DummyFunc<int, bool>.Instance, DummyFunc<int, int>.Instance, DummyFunc<int, int>.Instance, DummyFunc<int, DateTimeOffset>.Instance, null));
  269. ReactiveAssert.Throws<ArgumentNullException>(() => Observable.Generate(0, null, DummyFunc<int, int>.Instance, DummyFunc<int, int>.Instance, DummyFunc<int, DateTimeOffset>.Instance, DummyScheduler.Instance));
  270. ReactiveAssert.Throws<ArgumentNullException>(() => Observable.Generate(0, DummyFunc<int, bool>.Instance, DummyFunc<int, int>.Instance, (Func<int, int>)null, DummyFunc<int, DateTimeOffset>.Instance, DummyScheduler.Instance));
  271. ReactiveAssert.Throws<ArgumentNullException>(() => Observable.Generate(0, DummyFunc<int, bool>.Instance, null, DummyFunc<int, int>.Instance, DummyFunc<int, DateTimeOffset>.Instance, DummyScheduler.Instance));
  272. ReactiveAssert.Throws<ArgumentNullException>(() => Observable.Generate(0, DummyFunc<int, bool>.Instance, DummyFunc<int, int>.Instance, DummyFunc<int, int>.Instance, (Func<int, DateTimeOffset>)null, DummyScheduler.Instance));
  273. ReactiveAssert.Throws<ArgumentNullException>(() => Observable.Generate(0, DummyFunc<int, bool>.Instance, DummyFunc<int, int>.Instance, DummyFunc<int, int>.Instance, DummyFunc<int, DateTimeOffset>.Instance, DummyScheduler.Instance).Subscribe(null));
  274. }
  275. [TestMethod]
  276. public void Generate_DateTimeOffset_Finite()
  277. {
  278. var scheduler = new TestScheduler();
  279. var res = scheduler.Start(() =>
  280. Observable.Generate(0, x => x <= 3, x => x + 1, x => x, x => scheduler.Now.AddTicks(x + 1), scheduler)
  281. );
  282. res.Messages.AssertEqual(
  283. OnNext(202, 0),
  284. OnNext(204, 1),
  285. OnNext(207, 2),
  286. OnNext(211, 3),
  287. OnCompleted<int>(211)
  288. );
  289. }
  290. [TestMethod]
  291. public void Generate_DateTimeOffset_Throw_Condition()
  292. {
  293. var scheduler = new TestScheduler();
  294. var ex = new Exception();
  295. var res = scheduler.Start(() =>
  296. Observable.Generate(0, new Func<int, bool>(x => { throw ex; }), x => x + 1, x => x, x => scheduler.Now.AddTicks(x + 1), scheduler)
  297. );
  298. res.Messages.AssertEqual(
  299. OnError<int>(201, ex)
  300. );
  301. }
  302. [TestMethod]
  303. public void Generate_DateTimeOffset_Throw_ResultSelector()
  304. {
  305. var scheduler = new TestScheduler();
  306. var ex = new Exception();
  307. var res = scheduler.Start(() =>
  308. Observable.Generate(0, x => true, x => x + 1, new Func<int, int>(x => { throw ex; }), x => scheduler.Now.AddTicks(x + 1), scheduler)
  309. );
  310. res.Messages.AssertEqual(
  311. OnError<int>(201, ex)
  312. );
  313. }
  314. [TestMethod]
  315. public void Generate_DateTimeOffset_Throw_Iterate()
  316. {
  317. var scheduler = new TestScheduler();
  318. var ex = new Exception();
  319. var res = scheduler.Start(() =>
  320. Observable.Generate(0, x => true, new Func<int, int>(x => { throw ex; }), x => x, x => scheduler.Now.AddTicks(x + 1), scheduler)
  321. );
  322. res.Messages.AssertEqual(
  323. OnNext(202, 0),
  324. OnError<int>(202, ex)
  325. );
  326. }
  327. [TestMethod]
  328. public void Generate_DateTimeOffset_Throw_TimeSelector()
  329. {
  330. var scheduler = new TestScheduler();
  331. var ex = new Exception();
  332. var res = scheduler.Start(() =>
  333. Observable.Generate(0, x => true, x => x + 1, x => x, new Func<int, DateTimeOffset>(x => { throw ex; }), scheduler)
  334. );
  335. res.Messages.AssertEqual(
  336. OnError<int>(201, ex)
  337. );
  338. }
  339. [TestMethod]
  340. public void Generate_DateTimeOffset_Dispose()
  341. {
  342. var scheduler = new TestScheduler();
  343. var res = scheduler.Start(() =>
  344. Observable.Generate(0, x => true, x => x + 1, x => x, x => scheduler.Now.AddTicks(x + 1), scheduler),
  345. 210
  346. );
  347. res.Messages.AssertEqual(
  348. OnNext(202, 0),
  349. OnNext(204, 1),
  350. OnNext(207, 2)
  351. );
  352. }
  353. [TestMethod]
  354. public void Generate_DateTimeOffset_DefaultScheduler_ArgumentChecking()
  355. {
  356. ReactiveAssert.Throws<ArgumentNullException>(() => Observable.Generate(0, null, DummyFunc<int, int>.Instance, DummyFunc<int, int>.Instance, DummyFunc<int, DateTimeOffset>.Instance));
  357. ReactiveAssert.Throws<ArgumentNullException>(() => Observable.Generate(0, DummyFunc<int, bool>.Instance, DummyFunc<int, int>.Instance, (Func<int, int>)null, DummyFunc<int, DateTimeOffset>.Instance));
  358. ReactiveAssert.Throws<ArgumentNullException>(() => Observable.Generate(0, DummyFunc<int, bool>.Instance, null, DummyFunc<int, int>.Instance, DummyFunc<int, DateTimeOffset>.Instance));
  359. ReactiveAssert.Throws<ArgumentNullException>(() => Observable.Generate(0, DummyFunc<int, bool>.Instance, DummyFunc<int, int>.Instance, DummyFunc<int, int>.Instance, (Func<int, DateTimeOffset>)null));
  360. ReactiveAssert.Throws<ArgumentNullException>(() => Observable.Generate(0, DummyFunc<int, bool>.Instance, DummyFunc<int, int>.Instance, DummyFunc<int, int>.Instance, DummyFunc<int, DateTimeOffset>.Instance).Subscribe(null));
  361. }
  362. [TestMethod]
  363. public void Generate_DateTimeOffset_DefaultScheduler()
  364. {
  365. Observable.Generate(0, x => x < 10, x => x + 1, x => x, x => DateTimeOffset.Now.AddMilliseconds(x)).AssertEqual(Observable.Generate(0, x => x < 10, x => x + 1, x => x, x => DateTimeOffset.Now.AddMilliseconds(x), DefaultScheduler.Instance));
  366. }
  367. [TestMethod]
  368. public void Generate_TimeSpan_DisposeLater()
  369. {
  370. var count = 0;
  371. var d = Observable.Generate(0, i => true, i => i + 1, i => i, _ => TimeSpan.Zero)
  372. .WithLatestFrom(Observable.Return(1).Concat(Observable.Never<int>()), (a, b) => a)
  373. .Subscribe(v => Volatile.Write(ref count, v));
  374. while (Volatile.Read(ref count) < 10000)
  375. {
  376. Thread.Sleep(10);
  377. }
  378. d.Dispose();
  379. }
  380. [TestMethod]
  381. public void Generate_DateTimeOffset_DisposeLater()
  382. {
  383. var count = 0;
  384. var d = Observable.Generate(0, i => true, i => i + 1, i => i, _ => DateTimeOffset.Now)
  385. .WithLatestFrom(Observable.Return(1).Concat(Observable.Never<int>()), (a, b) => a)
  386. .Subscribe(v => Volatile.Write(ref count, v));
  387. while (Volatile.Read(ref count) < 10000)
  388. {
  389. Thread.Sleep(10);
  390. }
  391. d.Dispose();
  392. }
  393. #endregion
  394. }
  395. }