ToEventPatternTest.cs 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  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.Text;
  8. using System.Threading.Tasks;
  9. using System.Reactive;
  10. using System.Reactive.Concurrency;
  11. using System.Reactive.Linq;
  12. using Microsoft.Reactive.Testing;
  13. using Xunit;
  14. using ReactiveTests.Dummies;
  15. using System.Reflection;
  16. using System.Reactive.Subjects;
  17. namespace ReactiveTests.Tests
  18. {
  19. public class ToEventPatternTest : ReactiveTest
  20. {
  21. [Fact]
  22. public void ToEventPattern_ArgumentChecking()
  23. {
  24. ReactiveAssert.Throws<ArgumentNullException>(() => Observable.ToEventPattern<EventArgs>(null));
  25. }
  26. [Fact]
  27. public void ToEventPattern_IEvent()
  28. {
  29. var src = new Subject<EventPattern<EventArgs<int>>>();
  30. var evt = src.ToEventPattern();
  31. var snd = new object();
  32. var lst = new List<int>();
  33. var hnd = new EventHandler<EventArgs<int>>((s, e) =>
  34. {
  35. Assert.Same(snd, s);
  36. lst.Add(e.Value);
  37. });
  38. evt.OnNext += hnd;
  39. src.OnNext(new EventPattern<EventArgs<int>>(snd, new EventArgs<int>(42)));
  40. src.OnNext(new EventPattern<EventArgs<int>>(snd, new EventArgs<int>(43)));
  41. evt.OnNext -= hnd;
  42. src.OnNext(new EventPattern<EventArgs<int>>(snd, new EventArgs<int>(44)));
  43. Assert.True(lst.SequenceEqual(new[] { 42, 43 }));
  44. }
  45. [Fact]
  46. public void ToEventPattern_IEvent_Fails()
  47. {
  48. var src = new Subject<EventPattern<EventArgs<int>>>();
  49. var evt = src.ToEventPattern();
  50. var snd = new object();
  51. var lst = new List<int>();
  52. var hnd = new EventHandler<EventArgs<int>>((s, e) =>
  53. {
  54. Assert.Same(snd, s);
  55. lst.Add(e.Value);
  56. });
  57. evt.OnNext += hnd;
  58. src.OnNext(new EventPattern<EventArgs<int>>(snd, new EventArgs<int>(42)));
  59. src.OnNext(new EventPattern<EventArgs<int>>(snd, new EventArgs<int>(43)));
  60. var ex = new Exception();
  61. ReactiveAssert.Throws(ex, () => src.OnError(ex));
  62. Assert.True(lst.SequenceEqual(new[] { 42, 43 }));
  63. }
  64. [Fact]
  65. public void ToEventPattern_IEvent_Completes()
  66. {
  67. var src = new Subject<EventPattern<EventArgs<int>>>();
  68. var evt = src.ToEventPattern();
  69. var snd = new object();
  70. var lst = new List<int>();
  71. var hnd = new EventHandler<EventArgs<int>>((s, e) =>
  72. {
  73. Assert.Same(snd, s);
  74. lst.Add(e.Value);
  75. });
  76. evt.OnNext += hnd;
  77. src.OnNext(new EventPattern<EventArgs<int>>(snd, new EventArgs<int>(42)));
  78. src.OnNext(new EventPattern<EventArgs<int>>(snd, new EventArgs<int>(43)));
  79. src.OnCompleted();
  80. Assert.True(lst.SequenceEqual(new[] { 42, 43 }));
  81. }
  82. class EventSrc
  83. {
  84. public event EventHandler<EventArgs<string>> E;
  85. public void On(string s)
  86. {
  87. var e = E;
  88. if (e != null)
  89. e(this, new EventArgs<string>(s));
  90. }
  91. }
  92. class EventArgs<T> : EventArgs
  93. {
  94. public T Value { get; private set; }
  95. public EventArgs(T value)
  96. {
  97. Value = value;
  98. }
  99. }
  100. [Fact]
  101. public void FromEventPattern_ToEventPattern()
  102. {
  103. var src = new EventSrc();
  104. var evt = Observable.FromEventPattern<EventHandler<EventArgs<string>>, EventArgs<string>>(h => new EventHandler<EventArgs<string>>(h), h => src.E += h, h => src.E -= h);
  105. var res = evt.ToEventPattern();
  106. var lst = new List<string>();
  107. var hnd = new EventHandler<EventArgs<string>>((s, e) =>
  108. {
  109. Assert.Same(src, s);
  110. lst.Add(e.Value);
  111. });
  112. src.On("bar");
  113. res.OnNext += hnd;
  114. src.On("foo");
  115. src.On("baz");
  116. res.OnNext -= hnd;
  117. src.On("qux");
  118. Assert.True(lst.SequenceEqual(new[] { "foo", "baz" }));
  119. }
  120. [Fact]
  121. public void ToEvent_DuplicateHandlers()
  122. {
  123. var src = new Subject<Unit>();
  124. var evt = src.ToEvent();
  125. var num = 0;
  126. var hnd = new Action<Unit>(e => num++);
  127. evt.OnNext += hnd;
  128. Assert.Equal(0, num);
  129. src.OnNext(new Unit());
  130. Assert.Equal(1, num);
  131. evt.OnNext += hnd;
  132. src.OnNext(new Unit());
  133. Assert.Equal(3, num);
  134. evt.OnNext -= hnd;
  135. src.OnNext(new Unit());
  136. Assert.Equal(4, num);
  137. evt.OnNext -= hnd;
  138. src.OnNext(new Unit());
  139. Assert.Equal(4, num);
  140. }
  141. [Fact]
  142. public void ToEvent_SourceCompletes()
  143. {
  144. var src = new Subject<Unit>();
  145. var evt = src.ToEvent();
  146. var num = 0;
  147. var hnd = new Action<Unit>(e => num++);
  148. evt.OnNext += hnd;
  149. Assert.Equal(0, num);
  150. src.OnNext(new Unit());
  151. Assert.Equal(1, num);
  152. src.OnNext(new Unit());
  153. Assert.Equal(2, num);
  154. src.OnCompleted();
  155. Assert.Equal(2, num);
  156. var tbl = GetSubscriptionTable(evt);
  157. Assert.True(tbl.Count == 0);
  158. }
  159. [Fact]
  160. public void ToEvent_SourceFails()
  161. {
  162. var src = new Subject<Unit>();
  163. var evt = src.ToEvent();
  164. var num = 0;
  165. var hnd = new Action<Unit>(e => num++);
  166. evt.OnNext += hnd;
  167. Assert.Equal(0, num);
  168. src.OnNext(new Unit());
  169. Assert.Equal(1, num);
  170. src.OnNext(new Unit());
  171. Assert.Equal(2, num);
  172. var ex = new Exception();
  173. ReactiveAssert.Throws(ex, () => src.OnError(ex));
  174. var tbl = GetSubscriptionTable(evt);
  175. Assert.True(tbl.Count == 0);
  176. }
  177. [Fact]
  178. public void ToEvent_DoneImmediately()
  179. {
  180. var src = Observable.Empty<Unit>();
  181. var evt = src.ToEvent();
  182. var num = 0;
  183. var hnd = new Action<Unit>(e => num++);
  184. for (int i = 0; i < 2; i++)
  185. {
  186. evt.OnNext += hnd;
  187. Assert.Equal(0, num);
  188. var tbl = GetSubscriptionTable(evt);
  189. Assert.True(tbl.Count == 0);
  190. }
  191. }
  192. [Fact]
  193. public void ToEvent_UnbalancedHandlers()
  194. {
  195. var src = new Subject<Unit>();
  196. var evt = src.ToEvent();
  197. var num = 0;
  198. var hnd = new Action<Unit>(e => num++);
  199. evt.OnNext += hnd;
  200. Assert.Equal(0, num);
  201. evt.OnNext -= hnd;
  202. Assert.Equal(0, num);
  203. evt.OnNext -= hnd;
  204. Assert.Equal(0, num);
  205. evt.OnNext += hnd;
  206. Assert.Equal(0, num);
  207. src.OnNext(new Unit());
  208. Assert.Equal(1, num);
  209. src.OnNext(new Unit());
  210. Assert.Equal(2, num);
  211. evt.OnNext -= hnd;
  212. Assert.Equal(2, num);
  213. src.OnNext(new Unit());
  214. Assert.Equal(2, num);
  215. }
  216. private static Dictionary<Delegate, Stack<IDisposable>> GetSubscriptionTable(object evt)
  217. {
  218. return (Dictionary<Delegate, Stack<IDisposable>>)evt.GetType().GetField("_subscriptions", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(evt);
  219. }
  220. [Fact]
  221. public void EventPattern_Equality()
  222. {
  223. var e1 = new EventPattern<string, EventArgs>("Bart", EventArgs.Empty);
  224. var e2 = new EventPattern<string, EventArgs>("Bart", EventArgs.Empty);
  225. Assert.True(e1.Equals(e1));
  226. Assert.True(e1.Equals(e2));
  227. Assert.True(e2.Equals(e1));
  228. Assert.True(e1 == e2);
  229. Assert.True(!(e1 != e2));
  230. Assert.True(e1.GetHashCode() == e2.GetHashCode());
  231. Assert.False(e1.Equals(null));
  232. Assert.False(e1.Equals("xy"));
  233. Assert.False(e1 == null);
  234. }
  235. [Fact]
  236. public void EventPattern_Inequality()
  237. {
  238. var a1 = new MyEventArgs();
  239. var a2 = new MyEventArgs();
  240. var e1 = new EventPattern<string, MyEventArgs>("Bart", a1);
  241. var e2 = new EventPattern<string, MyEventArgs>("John", a1);
  242. var e3 = new EventPattern<string, MyEventArgs>("Bart", a2);
  243. Assert.True(!e1.Equals(e2));
  244. Assert.True(!e2.Equals(e1));
  245. Assert.True(!(e1 == e2));
  246. Assert.True(e1 != e2);
  247. Assert.True(e1.GetHashCode() != e2.GetHashCode());
  248. Assert.True(!e1.Equals(e3));
  249. Assert.True(!e3.Equals(e1));
  250. Assert.True(!(e1 == e3));
  251. Assert.True(e1 != e3);
  252. Assert.True(e1.GetHashCode() != e3.GetHashCode());
  253. }
  254. class MyEventArgs : EventArgs
  255. {
  256. }
  257. }
  258. }