DisposableTests.cs 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718
  1. // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
  2. using System;
  3. using System.Collections;
  4. using System.Collections.Generic;
  5. using System.Linq;
  6. using System.Reactive.Concurrency;
  7. using System.Reactive.Disposables;
  8. using System.Threading;
  9. using Microsoft.Reactive.Testing;
  10. using Microsoft.VisualStudio.TestTools.UnitTesting;
  11. namespace ReactiveTests.Tests
  12. {
  13. [TestClass]
  14. public class DisposableTests
  15. {
  16. [TestMethod]
  17. public void AnonymousDisposable_Create()
  18. {
  19. var d = Disposable.Create(() => { });
  20. Assert.IsNotNull(d);
  21. }
  22. [TestMethod, ExpectedException(typeof(ArgumentNullException))]
  23. public void AnonymousDisposable_CreateNull()
  24. {
  25. Disposable.Create(null);
  26. }
  27. [TestMethod]
  28. public void AnonymousDisposable_Dispose()
  29. {
  30. var disposed = false;
  31. var d = Disposable.Create(() => { disposed = true; });
  32. Assert.IsFalse(disposed);
  33. d.Dispose();
  34. Assert.IsTrue(disposed);
  35. var c = d as ICancelable;
  36. Assert.IsNotNull(c);
  37. Assert.IsTrue(c.IsDisposed);
  38. }
  39. [TestMethod]
  40. public void EmptyDisposable()
  41. {
  42. var d = Disposable.Empty;
  43. Assert.IsNotNull(d);
  44. d.Dispose();
  45. }
  46. [TestMethod]
  47. public void BooleanDisposable()
  48. {
  49. var d = new BooleanDisposable();
  50. Assert.IsFalse(d.IsDisposed);
  51. d.Dispose();
  52. Assert.IsTrue(d.IsDisposed);
  53. d.Dispose();
  54. Assert.IsTrue(d.IsDisposed);
  55. }
  56. [TestMethod]
  57. public void SingleAssignmentDisposable_SetNull()
  58. {
  59. var d = new SingleAssignmentDisposable();
  60. d.Disposable = null;
  61. }
  62. [TestMethod]
  63. public void SingleAssignmentDisposable_DisposeAfterSet()
  64. {
  65. var disposed = false;
  66. var d = new SingleAssignmentDisposable();
  67. var dd = Disposable.Create(() => { disposed = true; });
  68. d.Disposable = dd;
  69. Assert.AreSame(dd, d.Disposable);
  70. Assert.IsFalse(disposed);
  71. d.Dispose();
  72. Assert.IsTrue(disposed);
  73. d.Dispose();
  74. Assert.IsTrue(disposed);
  75. Assert.IsTrue(d.IsDisposed);
  76. }
  77. [TestMethod]
  78. public void SingleAssignmentDisposable_DisposeBeforeSet()
  79. {
  80. var disposed = false;
  81. var d = new SingleAssignmentDisposable();
  82. var dd = Disposable.Create(() => { disposed = true; });
  83. Assert.IsFalse(disposed);
  84. d.Dispose();
  85. Assert.IsFalse(disposed);
  86. Assert.IsTrue(d.IsDisposed);
  87. d.Disposable = dd;
  88. Assert.IsTrue(disposed);
  89. //Assert.IsNull(d.Disposable); // BREAKING CHANGE v2 > v1.x - Undefined behavior after disposal.
  90. d.Disposable.Dispose(); // This should be a nop.
  91. d.Dispose();
  92. Assert.IsTrue(disposed);
  93. }
  94. [TestMethod]
  95. public void SingleAssignmentDisposable_SetMultipleTimes()
  96. {
  97. var d = new SingleAssignmentDisposable();
  98. d.Disposable = Disposable.Empty;
  99. ReactiveAssert.Throws<InvalidOperationException>(() => { d.Disposable = Disposable.Empty; });
  100. }
  101. [TestMethod]
  102. public void CompositeDisposable_ArgumentChecking()
  103. {
  104. ReactiveAssert.Throws<ArgumentNullException>(() => new CompositeDisposable(default(IDisposable[])));
  105. ReactiveAssert.Throws<ArgumentNullException>(() => new CompositeDisposable(default(IEnumerable<IDisposable>)));
  106. ReactiveAssert.Throws<ArgumentOutOfRangeException>(() => new CompositeDisposable(-1));
  107. }
  108. [TestMethod]
  109. public void CompositeDisposable_Contains()
  110. {
  111. var d1 = Disposable.Create(() => {} );
  112. var d2 = Disposable.Create(() => { });
  113. var g = new CompositeDisposable(d1, d2);
  114. Assert.AreEqual(2, g.Count);
  115. Assert.IsTrue(g.Contains(d1));
  116. Assert.IsTrue(g.Contains(d2));
  117. ReactiveAssert.Throws<ArgumentNullException>(() => g.Contains(null));
  118. }
  119. [TestMethod]
  120. public void CompositeDisposable_IsReadOnly()
  121. {
  122. Assert.IsFalse(new CompositeDisposable().IsReadOnly);
  123. }
  124. [TestMethod, ExpectedException(typeof(ArgumentNullException))]
  125. public void CompositeDisposable_CopyTo_Null()
  126. {
  127. new CompositeDisposable().CopyTo(null, 0);
  128. }
  129. [TestMethod, ExpectedException(typeof(ArgumentOutOfRangeException))]
  130. public void CompositeDisposable_CopyTo_Negative()
  131. {
  132. new CompositeDisposable().CopyTo(new IDisposable[2], -1);
  133. }
  134. [TestMethod, ExpectedException(typeof(ArgumentOutOfRangeException))]
  135. public void CompositeDisposable_CopyTo_BeyondEnd()
  136. {
  137. new CompositeDisposable().CopyTo(new IDisposable[2], 2);
  138. }
  139. [TestMethod]
  140. public void CompositeDisposable_CopyTo()
  141. {
  142. var d1 = Disposable.Create(() => { });
  143. var d2 = Disposable.Create(() => { });
  144. var g = new CompositeDisposable(new List<IDisposable> { d1, d2 });
  145. var d = new IDisposable[3];
  146. g.CopyTo(d, 1);
  147. Assert.AreSame(d1, d[1]);
  148. Assert.AreSame(d2, d[2]);
  149. }
  150. [TestMethod]
  151. public void CompositeDisposable_ToArray()
  152. {
  153. var d1 = Disposable.Create(() => { });
  154. var d2 = Disposable.Create(() => { });
  155. var g = new CompositeDisposable(d1, d2);
  156. Assert.AreEqual(2, g.Count);
  157. var x = Enumerable.ToArray(g);
  158. Assert.IsTrue(g.ToArray().SequenceEqual(new[] { d1, d2 }));
  159. }
  160. [TestMethod]
  161. public void CompositeDisposable_GetEnumerator()
  162. {
  163. var d1 = Disposable.Create(() => { });
  164. var d2 = Disposable.Create(() => { });
  165. var g = new CompositeDisposable(d1, d2);
  166. var lst = new List<IDisposable>();
  167. foreach (var x in g)
  168. lst.Add(x);
  169. Assert.IsTrue(lst.SequenceEqual(new[] { d1, d2 }));
  170. }
  171. [TestMethod]
  172. public void CompositeDisposable_GetEnumeratorNonGeneric()
  173. {
  174. var d1 = Disposable.Create(() => { });
  175. var d2 = Disposable.Create(() => { });
  176. var g = new CompositeDisposable(d1, d2);
  177. var lst = new List<IDisposable>();
  178. foreach (IDisposable x in (IEnumerable)g)
  179. lst.Add(x);
  180. Assert.IsTrue(lst.SequenceEqual(new[] { d1, d2 }));
  181. }
  182. [TestMethod]
  183. public void CompositeDisposable_CollectionInitializer()
  184. {
  185. var d1 = Disposable.Create(() => { });
  186. var d2 = Disposable.Create(() => { });
  187. var g = new CompositeDisposable { d1, d2 };
  188. Assert.AreEqual(2, g.Count);
  189. Assert.IsTrue(g.Contains(d1));
  190. Assert.IsTrue(g.Contains(d2));
  191. }
  192. [TestMethod, ExpectedException(typeof(ArgumentException))]
  193. public void CompositeDisposable_AddNull_via_params_ctor()
  194. {
  195. IDisposable d1 = null;
  196. new CompositeDisposable(d1);
  197. }
  198. [TestMethod, ExpectedException(typeof(ArgumentException))]
  199. public void CompositeDisposable_AddNull_via_IEnum_ctor()
  200. {
  201. IEnumerable<IDisposable> values = new IDisposable[] { null };
  202. new CompositeDisposable(values);
  203. }
  204. [TestMethod, ExpectedException(typeof(ArgumentNullException))]
  205. public void CompositeDisposable_AddNull()
  206. {
  207. new CompositeDisposable().Add(null);
  208. }
  209. [TestMethod]
  210. public void CompositeDisposable_Add()
  211. {
  212. var d1 = Disposable.Create(() => { });
  213. var d2 = Disposable.Create(() => { });
  214. var g = new CompositeDisposable(d1);
  215. Assert.AreEqual(1, g.Count);
  216. Assert.IsTrue(g.Contains(d1));
  217. g.Add(d2);
  218. Assert.AreEqual(2, g.Count);
  219. Assert.IsTrue(g.Contains(d2));
  220. }
  221. [TestMethod]
  222. public void CompositeDisposable_AddAfterDispose()
  223. {
  224. var disp1 = false;
  225. var disp2 = false;
  226. var d1 = Disposable.Create(() => { disp1 = true; });
  227. var d2 = Disposable.Create(() => { disp2 = true; });
  228. var g = new CompositeDisposable(d1);
  229. Assert.AreEqual(1, g.Count);
  230. g.Dispose();
  231. Assert.IsTrue(disp1);
  232. Assert.AreEqual(0, g.Count); // CHECK
  233. g.Add(d2);
  234. Assert.IsTrue(disp2);
  235. Assert.AreEqual(0, g.Count); // CHECK
  236. Assert.IsTrue(g.IsDisposed);
  237. }
  238. [TestMethod]
  239. public void CompositeDisposable_Remove()
  240. {
  241. var disp1 = false;
  242. var disp2 = false;
  243. var d1 = Disposable.Create(() => { disp1 = true; });
  244. var d2 = Disposable.Create(() => { disp2 = true; });
  245. var g = new CompositeDisposable(d1, d2);
  246. Assert.AreEqual(2, g.Count);
  247. Assert.IsTrue(g.Contains(d1));
  248. Assert.IsTrue(g.Contains(d2));
  249. Assert.IsTrue(g.Remove(d1));
  250. Assert.AreEqual(1, g.Count);
  251. Assert.IsFalse(g.Contains(d1));
  252. Assert.IsTrue(g.Contains(d2));
  253. Assert.IsTrue(disp1);
  254. Assert.IsTrue(g.Remove(d2));
  255. Assert.IsFalse(g.Contains(d1));
  256. Assert.IsFalse(g.Contains(d2));
  257. Assert.IsTrue(disp2);
  258. var disp3 = false;
  259. var d3 = Disposable.Create(() => { disp3 = true; });
  260. Assert.IsFalse(g.Remove(d3));
  261. Assert.IsFalse(disp3);
  262. }
  263. [TestMethod]
  264. public void CompositeDisposable_Clear()
  265. {
  266. var disp1 = false;
  267. var disp2 = false;
  268. var d1 = Disposable.Create(() => { disp1 = true; });
  269. var d2 = Disposable.Create(() => { disp2 = true; });
  270. var g = new CompositeDisposable(d1, d2);
  271. Assert.AreEqual(2, g.Count);
  272. g.Clear();
  273. Assert.IsTrue(disp1);
  274. Assert.IsTrue(disp2);
  275. Assert.AreEqual(0, g.Count);
  276. var disp3 = false;
  277. var d3 = Disposable.Create(() => { disp3 = true; });
  278. g.Add(d3);
  279. Assert.IsFalse(disp3);
  280. Assert.AreEqual(1, g.Count);
  281. }
  282. [TestMethod]
  283. public void CompositeDisposable_RemoveOptimizationBehavior()
  284. {
  285. var g = new CompositeDisposable();
  286. var m = new Dictionary<int, IDisposable>();
  287. var r = new List<int>();
  288. var N = 100;
  289. for (int i = 0; i < N; i++)
  290. {
  291. var j = i;
  292. var d = Disposable.Create(() => r.Add(j));
  293. m[j] = d;
  294. g.Add(d);
  295. }
  296. var d1 = Enumerable.Range(0, N).Where(i => i % 2 == 0).ToArray();
  297. foreach (var i in d1)
  298. g.Remove(m[i]);
  299. Assert.IsTrue(r.SequenceEqual(d1));
  300. var d2 = Enumerable.Range(0, N).Where(i => i % 3 == 0).ToArray();
  301. foreach (var i in d2)
  302. g.Remove(m[i]);
  303. Assert.IsTrue(r.SequenceEqual(d1.Concat(d2.Where(x => !d1.Any(y => x == y)))));
  304. var d3 = Enumerable.Range(0, N).Where(i => i % 5 == 0).ToArray();
  305. foreach (var i in d3)
  306. g.Remove(m[i]);
  307. Assert.IsTrue(r.SequenceEqual(d1.Concat(d2.Where(x => !d1.Any(y => x == y))).Concat(d3.Where(x => !d1.Any(y => x == y) && !d2.Any(y => x == y)))));
  308. g.Dispose();
  309. var z = r.Except(d1.Union(d2).Union(d3)).ToArray();
  310. Assert.IsTrue(z.SequenceEqual(Enumerable.Range(0, N).Where(i => !(i % 2 == 0 || i % 3 == 0 || i % 5 == 0))));
  311. }
  312. [TestMethod, ExpectedException(typeof(ArgumentNullException))]
  313. public void CompositeDisposable_RemoveNull()
  314. {
  315. new CompositeDisposable().Remove(null);
  316. }
  317. #if DESKTOPCLR40 || DESKTOPCLR45
  318. [TestMethod, ExpectedException(typeof(ArgumentNullException))]
  319. public void CancellationDisposable_Ctor_Null()
  320. {
  321. new CancellationDisposable(null);
  322. }
  323. [TestMethod]
  324. public void CancellationDisposable_DefaultCtor()
  325. {
  326. var c = new CancellationDisposable();
  327. Assert.IsNotNull(c.Token);
  328. Assert.IsFalse(c.Token.IsCancellationRequested);
  329. Assert.IsTrue(c.Token.CanBeCanceled);
  330. c.Dispose();
  331. Assert.IsTrue(c.IsDisposed);
  332. Assert.IsTrue(c.Token.IsCancellationRequested);
  333. }
  334. [TestMethod]
  335. public void CancellationDisposable_TokenCtor()
  336. {
  337. var t = new CancellationTokenSource();
  338. var c = new CancellationDisposable(t);
  339. Assert.IsTrue(t.Token == c.Token);
  340. Assert.IsFalse(c.Token.IsCancellationRequested);
  341. Assert.IsTrue(c.Token.CanBeCanceled);
  342. c.Dispose();
  343. Assert.IsTrue(c.IsDisposed);
  344. Assert.IsTrue(c.Token.IsCancellationRequested);
  345. }
  346. #endif
  347. [TestMethod, ExpectedException(typeof(ArgumentNullException))]
  348. public void ContextDisposable_CreateNullContext()
  349. {
  350. new ContextDisposable(null, Disposable.Empty);
  351. }
  352. [TestMethod, ExpectedException(typeof(ArgumentNullException))]
  353. public void ContextDisposable_CreateNullDisposable()
  354. {
  355. new ContextDisposable(new SynchronizationContext(), null);
  356. }
  357. [TestMethod]
  358. public void ContextDisposable()
  359. {
  360. var disp = false;
  361. var m = new MySync();
  362. var c = new ContextDisposable(m, Disposable.Create(() => { disp = true; }));
  363. Assert.AreSame(m, c.Context);
  364. Assert.IsFalse(m._disposed);
  365. Assert.IsFalse(disp);
  366. c.Dispose();
  367. Assert.IsTrue(c.IsDisposed);
  368. Assert.IsTrue(m._disposed);
  369. Assert.IsTrue(disp);
  370. }
  371. class MySync : SynchronizationContext
  372. {
  373. internal bool _disposed = false;
  374. public override void Post(SendOrPostCallback d, object state)
  375. {
  376. d(state);
  377. _disposed = true;
  378. }
  379. }
  380. [TestMethod]
  381. public void SerialDisposable_Ctor_Prop()
  382. {
  383. var m = new SerialDisposable();
  384. Assert.IsNull(m.Disposable);
  385. }
  386. [TestMethod]
  387. public void SerialDisposable_ReplaceBeforeDispose()
  388. {
  389. var disp1 = false;
  390. var disp2 = false;
  391. var m = new SerialDisposable();
  392. var d1 = Disposable.Create(() => { disp1 = true; });
  393. m.Disposable = d1;
  394. Assert.AreSame(d1, m.Disposable);
  395. Assert.IsFalse(disp1);
  396. var d2 = Disposable.Create(() => { disp2 = true; });
  397. m.Disposable = d2;
  398. Assert.AreSame(d2, m.Disposable);
  399. Assert.IsTrue(disp1);
  400. Assert.IsFalse(disp2);
  401. }
  402. [TestMethod]
  403. public void SerialDisposable_ReplaceAfterDispose()
  404. {
  405. var disp1 = false;
  406. var disp2 = false;
  407. var m = new SerialDisposable();
  408. m.Dispose();
  409. Assert.IsTrue(m.IsDisposed);
  410. var d1 = Disposable.Create(() => { disp1 = true; });
  411. m.Disposable = d1;
  412. Assert.IsNull(m.Disposable); // CHECK
  413. Assert.IsTrue(disp1);
  414. var d2 = Disposable.Create(() => { disp2 = true; });
  415. m.Disposable = d2;
  416. Assert.IsNull(m.Disposable); // CHECK
  417. Assert.IsTrue(disp2);
  418. }
  419. [TestMethod]
  420. public void SerialDisposable_Dispose()
  421. {
  422. var disp = false;
  423. var m = new SerialDisposable();
  424. var d = Disposable.Create(() => { disp = true; });
  425. m.Disposable = d;
  426. Assert.AreSame(d, m.Disposable);
  427. Assert.IsFalse(disp);
  428. m.Dispose();
  429. Assert.IsTrue(m.IsDisposed);
  430. Assert.IsTrue(disp);
  431. //Assert.IsNull(m.Disposable); // BREAKING CHANGE v2 > v1.x - Undefined behavior after disposal.
  432. }
  433. [TestMethod, ExpectedException(typeof(ArgumentNullException))]
  434. public void RefCountDisposable_Ctor_Null()
  435. {
  436. new RefCountDisposable(null);
  437. }
  438. [TestMethod]
  439. public void RefCountDisposable_SingleReference()
  440. {
  441. var d = new BooleanDisposable();
  442. var r = new RefCountDisposable(d);
  443. Assert.IsFalse(d.IsDisposed);
  444. r.Dispose();
  445. Assert.IsTrue(d.IsDisposed);
  446. r.Dispose();
  447. Assert.IsTrue(d.IsDisposed);
  448. }
  449. [TestMethod]
  450. public void RefCountDisposable_RefCounting()
  451. {
  452. var d = new BooleanDisposable();
  453. var r = new RefCountDisposable(d);
  454. Assert.IsFalse(d.IsDisposed);
  455. var d1 = r.GetDisposable();
  456. var d2 = r.GetDisposable();
  457. Assert.IsFalse(d.IsDisposed);
  458. d1.Dispose();
  459. Assert.IsFalse(d.IsDisposed);
  460. d2.Dispose();
  461. Assert.IsFalse(d.IsDisposed); // CHECK
  462. r.Dispose();
  463. Assert.IsTrue(d.IsDisposed);
  464. Assert.IsTrue(r.IsDisposed);
  465. var d3 = r.GetDisposable(); // CHECK
  466. d3.Dispose();
  467. }
  468. [TestMethod]
  469. public void RefCountDisposable_PrimaryDisposesFirst()
  470. {
  471. var d = new BooleanDisposable();
  472. var r = new RefCountDisposable(d);
  473. Assert.IsFalse(d.IsDisposed);
  474. var d1 = r.GetDisposable();
  475. var d2 = r.GetDisposable();
  476. Assert.IsFalse(d.IsDisposed);
  477. d1.Dispose();
  478. Assert.IsFalse(d.IsDisposed);
  479. r.Dispose();
  480. Assert.IsFalse(d.IsDisposed);
  481. d2.Dispose();
  482. Assert.IsTrue(d.IsDisposed);
  483. }
  484. [TestMethod]
  485. public void ScheduledDisposable_Null()
  486. {
  487. ReactiveAssert.Throws<ArgumentNullException>(() => new ScheduledDisposable(null, Disposable.Empty));
  488. ReactiveAssert.Throws<ArgumentNullException>(() => new ScheduledDisposable(Scheduler.Immediate, null));
  489. }
  490. [TestMethod]
  491. public void ScheduledDisposable()
  492. {
  493. var d = new BooleanDisposable();
  494. var s = new ScheduledDisposable(Scheduler.Immediate, d);
  495. Assert.IsFalse(d.IsDisposed);
  496. Assert.AreSame(Scheduler.Immediate, s.Scheduler);
  497. Assert.AreSame(d, s.Disposable);
  498. s.Dispose();
  499. Assert.IsTrue(d.IsDisposed);
  500. Assert.IsTrue(s.IsDisposed);
  501. Assert.AreSame(Scheduler.Immediate, s.Scheduler);
  502. //Assert.AreSame(d, s.Disposable); // BREAKING CHANGE v2 > v1.x - Undefined behavior after disposal.
  503. s.Disposable.Dispose(); // This should be a nop.
  504. }
  505. [TestMethod]
  506. public void MultipleAssignmentDisposable()
  507. {
  508. var m = new MultipleAssignmentDisposable();
  509. var disp1 = false;
  510. var d1 = Disposable.Create(() => { disp1 = true; });
  511. m.Disposable = d1;
  512. Assert.AreSame(d1, m.Disposable);
  513. Assert.IsFalse(m.IsDisposed);
  514. var disp2 = false;
  515. var d2 = Disposable.Create(() => { disp2 = true; });
  516. m.Disposable = d2;
  517. Assert.AreSame(d2, m.Disposable);
  518. Assert.IsFalse(m.IsDisposed);
  519. Assert.IsFalse(disp1);
  520. m.Dispose();
  521. Assert.IsTrue(disp2);
  522. Assert.IsTrue(m.IsDisposed);
  523. //Assert.IsNull(m.Disposable); // BREAKING CHANGE v2 > v1.x - Undefined behavior after disposal.
  524. m.Disposable.Dispose(); // This should be a nop.
  525. var disp3 = false;
  526. var d3 = Disposable.Create(() => { disp3 = true; });
  527. m.Disposable = d3;
  528. Assert.IsTrue(disp3);
  529. //Assert.IsNull(m.Disposable); // BREAKING CHANGE v2 > v1.x - Undefined behavior after disposal.
  530. m.Disposable.Dispose(); // This should be a nop.
  531. Assert.IsTrue(m.IsDisposed);
  532. }
  533. [TestMethod]
  534. public void StableCompositeDisposable_ArgumentChecking()
  535. {
  536. var d = Disposable.Empty;
  537. ReactiveAssert.Throws<ArgumentNullException>(() => StableCompositeDisposable.Create(null, d));
  538. ReactiveAssert.Throws<ArgumentNullException>(() => StableCompositeDisposable.Create(d, null));
  539. ReactiveAssert.Throws<ArgumentNullException>(() => StableCompositeDisposable.Create(default(IDisposable[])));
  540. ReactiveAssert.Throws<ArgumentNullException>(() => StableCompositeDisposable.Create(default(IEnumerable<IDisposable>)));
  541. ReactiveAssert.Throws<ArgumentException>(() => StableCompositeDisposable.Create(null, d, d));
  542. ReactiveAssert.Throws<ArgumentException>(() => StableCompositeDisposable.Create(d, null, d));
  543. ReactiveAssert.Throws<ArgumentException>(() => StableCompositeDisposable.Create(d, d, null));
  544. }
  545. [TestMethod]
  546. public void StableCompositeDisposable_Binary()
  547. {
  548. var disp1 = false;
  549. var d1 = Disposable.Create(() => { Assert.IsFalse(disp1); disp1 = true; });
  550. var disp2 = false;
  551. var d2 = Disposable.Create(() => { Assert.IsFalse(disp2); disp2 = true; });
  552. var d = StableCompositeDisposable.Create(d1, d2);
  553. Assert.IsFalse(disp1);
  554. Assert.IsFalse(disp2);
  555. Assert.IsFalse(d.IsDisposed);
  556. d.Dispose();
  557. Assert.IsTrue(disp1);
  558. Assert.IsTrue(disp2);
  559. Assert.IsTrue(d.IsDisposed);
  560. d.Dispose();
  561. Assert.IsTrue(disp1);
  562. Assert.IsTrue(disp2);
  563. Assert.IsTrue(d.IsDisposed);
  564. }
  565. [TestMethod]
  566. public void StableCompositeDisposable_Nary()
  567. {
  568. var disp1 = false;
  569. var d1 = Disposable.Create(() => { Assert.IsFalse(disp1); disp1 = true; });
  570. var disp2 = false;
  571. var d2 = Disposable.Create(() => { Assert.IsFalse(disp2); disp2 = true; });
  572. var disp3 = false;
  573. var d3 = Disposable.Create(() => { Assert.IsFalse(disp3); disp3 = true; });
  574. var d = StableCompositeDisposable.Create(d1, d2, d3);
  575. Assert.IsFalse(disp1);
  576. Assert.IsFalse(disp2);
  577. Assert.IsFalse(disp3);
  578. Assert.IsFalse(d.IsDisposed);
  579. d.Dispose();
  580. Assert.IsTrue(disp1);
  581. Assert.IsTrue(disp2);
  582. Assert.IsTrue(disp3);
  583. Assert.IsTrue(d.IsDisposed);
  584. d.Dispose();
  585. Assert.IsTrue(disp1);
  586. Assert.IsTrue(disp2);
  587. Assert.IsTrue(disp3);
  588. Assert.IsTrue(d.IsDisposed);
  589. }
  590. }
  591. }