DistinctTest.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450
  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.Collections.Generic;
  6. using System.Linq;
  7. using System.Reactive.Linq;
  8. using Microsoft.Reactive.Testing;
  9. using ReactiveTests.Dummies;
  10. using Xunit;
  11. namespace ReactiveTests.Tests
  12. {
  13. public class DistinctTest : ReactiveTest
  14. {
  15. [Fact]
  16. public void Distinct_ArgumentChecking()
  17. {
  18. ReactiveAssert.Throws<ArgumentNullException>(() => Observable.Distinct(default(IObservable<int>)));
  19. ReactiveAssert.Throws<ArgumentNullException>(() => Observable.Distinct(default, EqualityComparer<int>.Default));
  20. ReactiveAssert.Throws<ArgumentNullException>(() => Observable.Distinct(DummyObservable<int>.Instance, default(EqualityComparer<int>)));
  21. ReactiveAssert.Throws<ArgumentNullException>(() => Observable.Distinct(default(IObservable<int>), x => x));
  22. ReactiveAssert.Throws<ArgumentNullException>(() => Observable.Distinct(DummyObservable<int>.Instance, default(Func<int, int>)));
  23. ReactiveAssert.Throws<ArgumentNullException>(() => Observable.Distinct(default(IObservable<int>), x => x, EqualityComparer<int>.Default));
  24. ReactiveAssert.Throws<ArgumentNullException>(() => Observable.Distinct(DummyObservable<int>.Instance, default, EqualityComparer<int>.Default));
  25. ReactiveAssert.Throws<ArgumentNullException>(() => Observable.Distinct(DummyObservable<int>.Instance, x => x, default(EqualityComparer<int>)));
  26. }
  27. [Fact]
  28. public void Distinct_DefaultComparer_AllDistinct()
  29. {
  30. var scheduler = new TestScheduler();
  31. var xs = scheduler.CreateHotObservable(
  32. OnNext(280, 4),
  33. OnNext(300, 2),
  34. OnNext(350, 1),
  35. OnNext(380, 3),
  36. OnNext(400, 5),
  37. OnCompleted<int>(420)
  38. );
  39. var res = scheduler.Start(() =>
  40. xs.Distinct()
  41. );
  42. res.Messages.AssertEqual(
  43. OnNext(280, 4),
  44. OnNext(300, 2),
  45. OnNext(350, 1),
  46. OnNext(380, 3),
  47. OnNext(400, 5),
  48. OnCompleted<int>(420)
  49. );
  50. xs.Subscriptions.AssertEqual(
  51. Subscribe(200, 420)
  52. );
  53. }
  54. [Fact]
  55. public void Distinct_DefaultComparer_SomeDuplicates()
  56. {
  57. var scheduler = new TestScheduler();
  58. var xs = scheduler.CreateHotObservable(
  59. OnNext(280, 4),
  60. OnNext(300, 2),
  61. OnNext(350, 2),
  62. OnNext(380, 3),
  63. OnNext(400, 4),
  64. OnCompleted<int>(420)
  65. );
  66. var res = scheduler.Start(() =>
  67. xs.Distinct()
  68. );
  69. res.Messages.AssertEqual(
  70. OnNext(280, 4),
  71. OnNext(300, 2),
  72. OnNext(380, 3),
  73. OnCompleted<int>(420)
  74. );
  75. xs.Subscriptions.AssertEqual(
  76. Subscribe(200, 420)
  77. );
  78. }
  79. [Fact]
  80. public void Distinct_CustomComparer_AllDistinct()
  81. {
  82. var scheduler = new TestScheduler();
  83. var xs = scheduler.CreateHotObservable(
  84. OnNext(280, 4),
  85. OnNext(300, 2),
  86. OnNext(350, 1),
  87. OnNext(380, 3),
  88. OnNext(400, 5),
  89. OnCompleted<int>(420)
  90. );
  91. var res = scheduler.Start(() =>
  92. xs.Distinct(new ModComparer(10))
  93. );
  94. res.Messages.AssertEqual(
  95. OnNext(280, 4),
  96. OnNext(300, 2),
  97. OnNext(350, 1),
  98. OnNext(380, 3),
  99. OnNext(400, 5),
  100. OnCompleted<int>(420)
  101. );
  102. xs.Subscriptions.AssertEqual(
  103. Subscribe(200, 420)
  104. );
  105. }
  106. [Fact]
  107. public void Distinct_CustomComparer_SomeDuplicates()
  108. {
  109. var scheduler = new TestScheduler();
  110. var xs = scheduler.CreateHotObservable(
  111. OnNext(280, 4),
  112. OnNext(300, 2),
  113. OnNext(350, 12),
  114. OnNext(380, 3),
  115. OnNext(400, 24),
  116. OnCompleted<int>(420)
  117. );
  118. var res = scheduler.Start(() =>
  119. xs.Distinct(new ModComparer(10))
  120. );
  121. res.Messages.AssertEqual(
  122. OnNext(280, 4),
  123. OnNext(300, 2),
  124. OnNext(380, 3),
  125. OnCompleted<int>(420)
  126. );
  127. xs.Subscriptions.AssertEqual(
  128. Subscribe(200, 420)
  129. );
  130. }
  131. private class ModComparer : IEqualityComparer<int>
  132. {
  133. private readonly int _mod;
  134. public ModComparer(int mod)
  135. {
  136. _mod = mod;
  137. }
  138. public bool Equals(int x, int y)
  139. {
  140. return EqualityComparer<int>.Default.Equals(x % _mod, y % _mod);
  141. }
  142. public int GetHashCode(int obj)
  143. {
  144. return EqualityComparer<int>.Default.GetHashCode(obj % _mod);
  145. }
  146. }
  147. [Fact]
  148. public void Distinct_KeySelector_DefaultComparer_AllDistinct()
  149. {
  150. var scheduler = new TestScheduler();
  151. var xs = scheduler.CreateHotObservable(
  152. OnNext(280, 8),
  153. OnNext(300, 4),
  154. OnNext(350, 2),
  155. OnNext(380, 6),
  156. OnNext(400, 10),
  157. OnCompleted<int>(420)
  158. );
  159. var res = scheduler.Start(() =>
  160. xs.Distinct(x => x / 2)
  161. );
  162. res.Messages.AssertEqual(
  163. OnNext(280, 8),
  164. OnNext(300, 4),
  165. OnNext(350, 2),
  166. OnNext(380, 6),
  167. OnNext(400, 10),
  168. OnCompleted<int>(420)
  169. );
  170. xs.Subscriptions.AssertEqual(
  171. Subscribe(200, 420)
  172. );
  173. }
  174. [Fact]
  175. public void Distinct_KeySelector_DefaultComparer_SomeDuplicates()
  176. {
  177. var scheduler = new TestScheduler();
  178. var xs = scheduler.CreateHotObservable(
  179. OnNext(280, 4),
  180. OnNext(300, 2),
  181. OnNext(350, 3),
  182. OnNext(380, 7),
  183. OnNext(400, 5),
  184. OnCompleted<int>(420)
  185. );
  186. var res = scheduler.Start(() =>
  187. xs.Distinct(x => x / 2)
  188. );
  189. res.Messages.AssertEqual(
  190. OnNext(280, 4),
  191. OnNext(300, 2),
  192. OnNext(380, 7),
  193. OnCompleted<int>(420)
  194. );
  195. xs.Subscriptions.AssertEqual(
  196. Subscribe(200, 420)
  197. );
  198. }
  199. [Fact]
  200. public void Distinct_KeySelector_CustomComparer_AllDistinct()
  201. {
  202. var scheduler = new TestScheduler();
  203. var xs = scheduler.CreateHotObservable(
  204. OnNext(280, 8),
  205. OnNext(300, 4),
  206. OnNext(350, 2),
  207. OnNext(380, 6),
  208. OnNext(400, 10),
  209. OnCompleted<int>(420)
  210. );
  211. var res = scheduler.Start(() =>
  212. xs.Distinct(x => x / 2, new ModComparer(10))
  213. );
  214. res.Messages.AssertEqual(
  215. OnNext(280, 8),
  216. OnNext(300, 4),
  217. OnNext(350, 2),
  218. OnNext(380, 6),
  219. OnNext(400, 10),
  220. OnCompleted<int>(420)
  221. );
  222. xs.Subscriptions.AssertEqual(
  223. Subscribe(200, 420)
  224. );
  225. }
  226. [Fact]
  227. public void Distinct_KeySelector_CustomComparer_SomeDuplicates()
  228. {
  229. var scheduler = new TestScheduler();
  230. var xs = scheduler.CreateHotObservable(
  231. OnNext(280, 8),
  232. OnNext(300, 4),
  233. OnNext(350, 2),
  234. OnNext(380, 6),
  235. OnNext(400, 10),
  236. OnCompleted<int>(420)
  237. );
  238. var res = scheduler.Start(() =>
  239. xs.Distinct(x => x / 2, new ModComparer(3))
  240. );
  241. res.Messages.AssertEqual(
  242. OnNext(280, 8),
  243. OnNext(300, 4),
  244. OnNext(380, 6),
  245. OnCompleted<int>(420)
  246. );
  247. xs.Subscriptions.AssertEqual(
  248. Subscribe(200, 420)
  249. );
  250. }
  251. [Fact]
  252. public void Distinct_KeySelector_Throws()
  253. {
  254. var scheduler = new TestScheduler();
  255. var xs = scheduler.CreateHotObservable(
  256. OnNext(280, 3),
  257. OnNext(300, 2),
  258. OnNext(350, 1),
  259. OnNext(380, 0),
  260. OnNext(400, 4),
  261. OnCompleted<int>(420)
  262. );
  263. var ex = new Exception();
  264. var res = scheduler.Start(() =>
  265. xs.Distinct(x => { if (x == 0) { throw ex; } return x / 2; })
  266. );
  267. res.Messages.AssertEqual(
  268. OnNext(280, 3),
  269. OnNext(350, 1),
  270. OnError<int>(380, ex)
  271. );
  272. xs.Subscriptions.AssertEqual(
  273. Subscribe(200, 380)
  274. );
  275. }
  276. [Fact]
  277. public void Distinct_CustomComparer_Throws()
  278. {
  279. var scheduler = new TestScheduler();
  280. var xs = scheduler.CreateHotObservable(
  281. OnNext(280, 1),
  282. OnNext(300, 2),
  283. OnNext(350, 3),
  284. OnNext(380, 4),
  285. OnNext(400, 5),
  286. OnCompleted<int>(420)
  287. );
  288. var ex = new Exception();
  289. var res = scheduler.Start(() =>
  290. xs.Distinct(new ThrowComparer(4, ex))
  291. );
  292. res.Messages.AssertEqual(
  293. OnNext(280, 1),
  294. OnNext(300, 2),
  295. OnNext(350, 3),
  296. OnError<int>(380, ex)
  297. );
  298. xs.Subscriptions.AssertEqual(
  299. Subscribe(200, 380)
  300. );
  301. }
  302. private class ThrowComparer : IEqualityComparer<int>
  303. {
  304. private readonly int _err;
  305. private readonly Exception _ex;
  306. public ThrowComparer(int err, Exception ex)
  307. {
  308. _err = err;
  309. _ex = ex;
  310. }
  311. public bool Equals(int x, int y)
  312. {
  313. return EqualityComparer<int>.Default.Equals(x, y);
  314. }
  315. public int GetHashCode(int obj)
  316. {
  317. if (obj == _err)
  318. {
  319. throw _ex;
  320. }
  321. return EqualityComparer<int>.Default.GetHashCode(obj);
  322. }
  323. }
  324. [Fact]
  325. public void Distinct_Throw()
  326. {
  327. var scheduler = new TestScheduler();
  328. var ex = new Exception();
  329. var xs = scheduler.CreateHotObservable(
  330. OnNext(280, 1),
  331. OnNext(300, 2),
  332. OnNext(350, 3),
  333. OnError<int>(380, ex)
  334. );
  335. var res = scheduler.Start(() =>
  336. xs.Distinct()
  337. );
  338. res.Messages.AssertEqual(
  339. OnNext(280, 1),
  340. OnNext(300, 2),
  341. OnNext(350, 3),
  342. OnError<int>(380, ex)
  343. );
  344. xs.Subscriptions.AssertEqual(
  345. Subscribe(200, 380)
  346. );
  347. }
  348. [Fact]
  349. public void Distinct_Null()
  350. {
  351. var scheduler = new TestScheduler();
  352. var xs = scheduler.CreateHotObservable(
  353. OnNext(220, "bar"),
  354. OnNext(240, default(string)),
  355. OnNext(260, "bar"),
  356. OnNext(280, "foo"),
  357. OnNext(300, default(string)),
  358. OnCompleted<string>(400)
  359. );
  360. var res = scheduler.Start(() =>
  361. xs.Distinct()
  362. );
  363. res.Messages.AssertEqual(
  364. OnNext(220, "bar"),
  365. OnNext(240, default(string)),
  366. OnNext(280, "foo"),
  367. OnCompleted<string>(400)
  368. );
  369. xs.Subscriptions.AssertEqual(
  370. Subscribe(200, 400)
  371. );
  372. }
  373. }
  374. }