1 // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
2 
3 using System;
4 using System.Reactive;
5 using System.Threading;
6 using Microsoft.Reactive.Testing;
7 #if NUNIT
8 using NUnit.Framework;
9 using TestClassAttribute = NUnit.Framework.TestFixtureAttribute;
10 using TestMethodAttribute = NUnit.Framework.TestAttribute;
11 using TestInitializeAttribute = NUnit.Framework.SetUpAttribute;
12 #else
13 using Microsoft.VisualStudio.TestTools.UnitTesting;
14 #endif
15 
16 namespace ReactiveTests.Tests
17 {
18     [TestClass]
19     public class NotificationTest : ReactiveTest
20     {
21         #region ToObservable
22 
23         [TestMethod]
ToObservable_ArgumentChecking()24         public void ToObservable_ArgumentChecking()
25         {
26             ReactiveAssert.Throws<ArgumentNullException>(() => Notification.CreateOnNext<int>(1).ToObservable(null));
27         }
28 
29         [TestMethod]
ToObservable_Empty()30         public void ToObservable_Empty()
31         {
32             var scheduler = new TestScheduler();
33 
34             var res = scheduler.Start(() =>
35                 Notification.CreateOnCompleted<int>().ToObservable(scheduler)
36             );
37 
38             res.Messages.AssertEqual(
39                 OnCompleted<int>(201)
40             );
41         }
42 
43         [TestMethod]
ToObservable_Return()44         public void ToObservable_Return()
45         {
46             var scheduler = new TestScheduler();
47 
48             var res = scheduler.Start(() =>
49                 Notification.CreateOnNext<int>(42).ToObservable(scheduler)
50             );
51 
52             res.Messages.AssertEqual(
53                 OnNext<int>(201, 42),
54                 OnCompleted<int>(201)
55             );
56         }
57 
58         [TestMethod]
ToObservable_Throw()59         public void ToObservable_Throw()
60         {
61             var ex = new Exception();
62 
63             var scheduler = new TestScheduler();
64 
65             var res = scheduler.Start(() =>
66                 Notification.CreateOnError<int>(ex).ToObservable(scheduler)
67             );
68 
69             res.Messages.AssertEqual(
70                 OnError<int>(201, ex)
71             );
72         }
73 
74         [TestMethod]
ToObservable_CurrentThread()75         public void ToObservable_CurrentThread()
76         {
77             var evt = new ManualResetEvent(false);
78 
79             Notification.CreateOnCompleted<int>().ToObservable().Subscribe(_ => { }, () =>
80             {
81                 evt.Set();
82             });
83 
84             evt.WaitOne();
85         }
86 
87         #endregion
88 
89         [TestMethod]
Notifications_Equality()90         public void Notifications_Equality()
91         {
92             var n = Notification.CreateOnNext(42);
93             var e = Notification.CreateOnError<int>(new Exception());
94             var c = Notification.CreateOnCompleted<int>();
95 
96             var n1 = n; var n2 = n;
97             var e1 = e; var e2 = e;
98             var c1 = c; var c2 = c;
99 
100             Assert.IsTrue(n1 == n2);
101             Assert.IsTrue(e1 == e2);
102             Assert.IsTrue(c1 == c2);
103 
104             Assert.IsTrue(n1.Equals(n2));
105             Assert.IsTrue(e1.Equals(e2));
106             Assert.IsTrue(c1.Equals(c2));
107         }
108 
109         [TestMethod]
OnNext_CtorAndProps()110         public void OnNext_CtorAndProps()
111         {
112             var n = Notification.CreateOnNext<int>(42);
113             Assert.AreEqual(NotificationKind.OnNext, n.Kind);
114             Assert.IsTrue(n.HasValue);
115             Assert.AreEqual(42, n.Value);
116             Assert.IsNull(n.Exception);
117         }
118 
119         [TestMethod]
OnNext_Equality()120         public void OnNext_Equality()
121         {
122             var n1 = Notification.CreateOnNext<int>(42);
123             var n2 = Notification.CreateOnNext<int>(42);
124             var n3 = Notification.CreateOnNext<int>(24);
125             var n4 = Notification.CreateOnCompleted<int>();
126 
127             Assert.IsTrue(n1.Equals(n1));
128             Assert.IsTrue(n1.Equals(n2));
129             Assert.IsTrue(n2.Equals(n1));
130 
131             Assert.IsFalse(n1.Equals(null));
132             Assert.IsFalse(n1.Equals(""));
133 
134             Assert.IsFalse(n1.Equals(n3));
135             Assert.IsFalse(n3.Equals(n1));
136             Assert.IsFalse(n1.Equals(n4));
137             Assert.IsFalse(n4.Equals(n1));
138 
139             Assert.IsTrue(n1 == n2);
140             Assert.IsTrue(n2 == n1);
141             Assert.IsFalse(n1 == null);
142             Assert.IsFalse(null == n1);
143             Assert.IsTrue(!(n1 != n2));
144             Assert.IsTrue(!(n2 != n1));
145             Assert.IsFalse(!(n1 != null));
146             Assert.IsFalse(!(null != n1));
147         }
148 
149         [TestMethod]
OnNext_GetHashCode()150         public void OnNext_GetHashCode()
151         {
152             var n1 = Notification.CreateOnNext<int>(42);
153             var n2 = Notification.CreateOnNext<int>(42);
154 
155             Assert.AreNotEqual(0, n1.GetHashCode());
156             Assert.AreEqual(n1.GetHashCode(), n2.GetHashCode());
157         }
158 
159         [TestMethod]
OnNext_ToString()160         public void OnNext_ToString()
161         {
162             var n1 = Notification.CreateOnNext<int>(42);
163             Assert.IsTrue(n1.ToString().Contains("OnNext"));
164             Assert.IsTrue(n1.ToString().Contains(42.ToString()));
165         }
166 
167         [TestMethod]
OnNext_AcceptObserver()168         public void OnNext_AcceptObserver()
169         {
170             var con = new CheckOnNextObserver();
171             var n1 = Notification.CreateOnNext<int>(42);
172             n1.Accept(con);
173 
174             Assert.AreEqual(42, con.Value);
175         }
176 
177         class CheckOnNextObserver : IObserver<int>
178         {
OnNext(int value)179             public void OnNext(int value)
180             {
181                 Value = value;
182             }
183 
184             public int Value { get; private set; }
185 
OnError(Exception exception)186             public void OnError(Exception exception)
187             {
188                 throw new NotImplementedException();
189             }
190 
OnCompleted()191             public void OnCompleted()
192             {
193                 throw new NotImplementedException();
194             }
195         }
196 
197         [TestMethod]
OnNext_AcceptObserverWithResult()198         public void OnNext_AcceptObserverWithResult()
199         {
200             var n1 = Notification.CreateOnNext<int>(42);
201             var res = n1.Accept(new AcceptObserver(x => "OK", _ => { Assert.Fail(); return null; }, () => { Assert.Fail(); return null; }));
202 
203             Assert.AreEqual("OK", res);
204         }
205 
206         [TestMethod]
OnNext_AcceptObserverWithResult_Null()207         public void OnNext_AcceptObserverWithResult_Null()
208         {
209             var n1 = Notification.CreateOnNext<int>(42);
210             ReactiveAssert.Throws<ArgumentNullException>(() => n1.Accept(default(IObserver<int, string>)));
211         }
212 
213         [TestMethod]
OnNext_AcceptAction()214         public void OnNext_AcceptAction()
215         {
216             var obs = false;
217 
218             var n1 = Notification.CreateOnNext<int>(42);
219             n1.Accept(x => { obs = true; }, _ => { Assert.Fail(); }, () => { Assert.Fail(); });
220 
221             Assert.IsTrue(obs);
222         }
223 
224         [TestMethod]
OnNext_Accept_ArgumentChecking()225         public void OnNext_Accept_ArgumentChecking()
226         {
227             var n = Notification.CreateOnNext<int>(42);
228 
229             ReactiveAssert.Throws<ArgumentNullException>(() => n.Accept(default(IObserver<int>)));
230 
231             ReactiveAssert.Throws<ArgumentNullException>(() => n.Accept(default(Action<int>), ex => { }, () => { }));
232             ReactiveAssert.Throws<ArgumentNullException>(() => n.Accept(x => { }, default(Action<Exception>), () => { }));
233             ReactiveAssert.Throws<ArgumentNullException>(() => n.Accept(x => { }, ex => { }, default(Action)));
234 
235             ReactiveAssert.Throws<ArgumentNullException>(() => n.Accept<string>(default(Func<int, string>), ex => "", () => ""));
236             ReactiveAssert.Throws<ArgumentNullException>(() => n.Accept<string>(x => "", default(Func<Exception, string>), () => ""));
237             ReactiveAssert.Throws<ArgumentNullException>(() => n.Accept<string>(x => "", ex => "", default(Func<string>)));
238         }
239 
240         [TestMethod]
OnNext_AcceptActionWithResult()241         public void OnNext_AcceptActionWithResult()
242         {
243             var n1 = Notification.CreateOnNext<int>(42);
244             var res = n1.Accept(x => "OK", _ => { Assert.Fail(); return null; }, () => { Assert.Fail(); return null; });
245 
246             Assert.AreEqual("OK", res);
247         }
248 
249         [TestMethod, ExpectedException(typeof(ArgumentNullException))]
OnError_CtorNull()250         public void OnError_CtorNull()
251         {
252             Notification.CreateOnError<int>(null);
253         }
254 
255         [TestMethod]
OnError_Accept_ArgumentChecking()256         public void OnError_Accept_ArgumentChecking()
257         {
258             var n = Notification.CreateOnError<int>(new Exception());
259 
260             ReactiveAssert.Throws<ArgumentNullException>(() => n.Accept(default(IObserver<int>)));
261 
262             ReactiveAssert.Throws<ArgumentNullException>(() => n.Accept(default(Action<int>), ex => { }, () => { }));
263             ReactiveAssert.Throws<ArgumentNullException>(() => n.Accept(x => { }, default(Action<Exception>), () => { }));
264             ReactiveAssert.Throws<ArgumentNullException>(() => n.Accept(x => { }, ex => { }, default(Action)));
265 
266             ReactiveAssert.Throws<ArgumentNullException>(() => n.Accept<string>(default(Func<int, string>), ex => "", () => ""));
267             ReactiveAssert.Throws<ArgumentNullException>(() => n.Accept<string>(x => "", default(Func<Exception, string>), () => ""));
268             ReactiveAssert.Throws<ArgumentNullException>(() => n.Accept<string>(x => "", ex => "", default(Func<string>)));
269         }
270 
271         [TestMethod]
OnError_CtorAndProps()272         public void OnError_CtorAndProps()
273         {
274             var e = new Exception();
275             var n = Notification.CreateOnError<int>(e);
276             Assert.AreEqual(NotificationKind.OnError, n.Kind);
277             Assert.IsFalse(n.HasValue);
278             Assert.AreSame(e, n.Exception);
279 
280             try
281             {
282                 var x = n.Value;
283                 Assert.Fail();
284             }
285             catch (Exception _e)
286             {
287                 Assert.AreSame(e, _e);
288             }
289         }
290 
291         [TestMethod]
OnError_Equality()292         public void OnError_Equality()
293         {
294             var ex1 = new Exception();
295             var ex2 = new Exception();
296 
297             var n1 = Notification.CreateOnError<int>(ex1);
298             var n2 = Notification.CreateOnError<int>(ex1);
299             var n3 = Notification.CreateOnError<int>(ex2);
300             var n4 = Notification.CreateOnCompleted<int>();
301 
302             Assert.IsTrue(n1.Equals(n1));
303             Assert.IsTrue(n1.Equals(n2));
304             Assert.IsTrue(n2.Equals(n1));
305 
306             Assert.IsFalse(n1.Equals(null));
307             Assert.IsFalse(n1.Equals(""));
308 
309             Assert.IsFalse(n1.Equals(n3));
310             Assert.IsFalse(n3.Equals(n1));
311             Assert.IsFalse(n1.Equals(n4));
312             Assert.IsFalse(n4.Equals(n1));
313 
314             Assert.IsTrue(n1 == n2);
315             Assert.IsTrue(n2 == n1);
316             Assert.IsFalse(n1 == null);
317             Assert.IsFalse(null == n1);
318             Assert.IsTrue(!(n1 != n2));
319             Assert.IsTrue(!(n2 != n1));
320             Assert.IsFalse(!(n1 != null));
321             Assert.IsFalse(!(null != n1));
322         }
323 
324         [TestMethod]
OnError_GetHashCode()325         public void OnError_GetHashCode()
326         {
327             var ex = new Exception();
328 
329             var n1 = Notification.CreateOnError<int>(ex);
330             var n2 = Notification.CreateOnError<int>(ex);
331 
332             Assert.AreNotEqual(0, n1.GetHashCode());
333             Assert.AreEqual(n1.GetHashCode(), n2.GetHashCode());
334         }
335 
336         [TestMethod]
OnError_ToString()337         public void OnError_ToString()
338         {
339             var ex = new Exception();
340 
341             var n1 = Notification.CreateOnError<int>(ex);
342             Assert.IsTrue(n1.ToString().Contains("OnError"));
343             Assert.IsTrue(n1.ToString().Contains(ex.GetType().Name)); // CHECK, no message?
344         }
345 
346         [TestMethod]
OnError_AcceptObserver()347         public void OnError_AcceptObserver()
348         {
349             var ex = new Exception();
350 
351             var obs = new CheckOnErrorObserver();
352 
353             var n1 = Notification.CreateOnError<int>(ex);
354             n1.Accept(obs);
355 
356             Assert.AreSame(ex, obs.Error);
357         }
358 
359         class CheckOnErrorObserver : IObserver<int>
360         {
OnNext(int value)361             public void OnNext(int value)
362             {
363                 throw new NotImplementedException();
364             }
365 
366             public Exception Error { get; private set; }
367 
OnError(Exception exception)368             public void OnError(Exception exception)
369             {
370                 Error = exception;
371             }
372 
OnCompleted()373             public void OnCompleted()
374             {
375                 throw new NotImplementedException();
376             }
377         }
378 
379         [TestMethod]
OnError_AcceptObserverWithResult()380         public void OnError_AcceptObserverWithResult()
381         {
382             var ex = new Exception();
383 
384             var n1 = Notification.CreateOnError<int>(ex);
385             var res = n1.Accept(new AcceptObserver(x => { Assert.Fail(); return null; }, _ => { Assert.AreSame(ex, _); return "OK"; }, () => { Assert.Fail(); return null; }));
386 
387             Assert.AreEqual("OK", res);
388         }
389 
390         [TestMethod]
OnError_AcceptObserverWithResult_Null()391         public void OnError_AcceptObserverWithResult_Null()
392         {
393             var n1 = Notification.CreateOnError<int>(new Exception());
394             ReactiveAssert.Throws<ArgumentNullException>(() => n1.Accept(default(IObserver<int, string>)));
395         }
396 
397         [TestMethod]
OnError_AcceptAction()398         public void OnError_AcceptAction()
399         {
400             var ex = new Exception();
401 
402             var obs = false;
403 
404             var n1 = Notification.CreateOnError<int>(ex);
405             n1.Accept(x => { Assert.Fail(); }, _ => { obs = true; }, () => { Assert.Fail(); });
406 
407             Assert.IsTrue(obs);
408         }
409 
410         [TestMethod]
OnError_AcceptActionWithResult()411         public void OnError_AcceptActionWithResult()
412         {
413             var ex = new Exception();
414 
415             var n1 = Notification.CreateOnError<int>(ex);
416             var res = n1.Accept(x => { Assert.Fail(); return null; }, x => "OK", () => { Assert.Fail(); return null; });
417 
418             Assert.AreEqual("OK", res);
419         }
420 
421         [TestMethod]
OnCompleted_CtorAndProps()422         public void OnCompleted_CtorAndProps()
423         {
424             var n = Notification.CreateOnCompleted<int>();
425             Assert.AreEqual(NotificationKind.OnCompleted, n.Kind);
426             Assert.IsFalse(n.HasValue);
427             Assert.IsNull(n.Exception);
428 
429             var ok = false;
430             try
431             {
432                 var x = n.Value;
433                 Assert.Fail();
434             }
435             catch (InvalidOperationException)
436             {
437                 ok = true;
438             }
439 
440             Assert.IsTrue(ok);
441         }
442 
443         [TestMethod]
OnCompleted_Accept_ArgumentChecking()444         public void OnCompleted_Accept_ArgumentChecking()
445         {
446             var n = Notification.CreateOnCompleted<int>();
447 
448             ReactiveAssert.Throws<ArgumentNullException>(() => n.Accept(default(IObserver<int>)));
449 
450             ReactiveAssert.Throws<ArgumentNullException>(() => n.Accept(default(Action<int>), ex => { }, () => { }));
451             ReactiveAssert.Throws<ArgumentNullException>(() => n.Accept(x => { }, default(Action<Exception>), () => { }));
452             ReactiveAssert.Throws<ArgumentNullException>(() => n.Accept(x => { }, ex => { }, default(Action)));
453 
454             ReactiveAssert.Throws<ArgumentNullException>(() => n.Accept<string>(default(Func<int, string>), ex => "", () => ""));
455             ReactiveAssert.Throws<ArgumentNullException>(() => n.Accept<string>(x => "", default(Func<Exception, string>), () => ""));
456             ReactiveAssert.Throws<ArgumentNullException>(() => n.Accept<string>(x => "", ex => "", default(Func<string>)));
457         }
458 
459         [TestMethod]
OnCompleted_Equality()460         public void OnCompleted_Equality()
461         {
462             var n1 = Notification.CreateOnCompleted<int>();
463             var n2 = Notification.CreateOnCompleted<int>();
464             var n3 = Notification.CreateOnNext<int>(2);
465 
466             Assert.IsTrue(n1.Equals(n1));
467             Assert.IsTrue(n1.Equals(n2));
468             Assert.IsTrue(n2.Equals(n1));
469 
470             Assert.IsFalse(n1.Equals(null));
471             Assert.IsFalse(n1.Equals(""));
472 
473             Assert.IsFalse(n1.Equals(n3));
474             Assert.IsFalse(n3.Equals(n1));
475 
476             Assert.IsTrue(n1 == n2);
477             Assert.IsTrue(n2 == n1);
478             Assert.IsFalse(n1 == null);
479             Assert.IsFalse(null == n1);
480             Assert.IsTrue(!(n1 != n2));
481             Assert.IsTrue(!(n2 != n1));
482             Assert.IsFalse(!(n1 != null));
483             Assert.IsFalse(!(null != n1));
484         }
485 
486         [TestMethod]
OnCompleted_GetHashCode()487         public void OnCompleted_GetHashCode()
488         {
489             var n1 = Notification.CreateOnCompleted<int>();
490             var n2 = Notification.CreateOnCompleted<int>();
491 
492             Assert.AreNotEqual(0, n1.GetHashCode());
493             Assert.AreEqual(n1.GetHashCode(), n2.GetHashCode());
494         }
495 
496         [TestMethod]
OnCompleted_ToString()497         public void OnCompleted_ToString()
498         {
499             var n1 = Notification.CreateOnCompleted<int>();
500             Assert.IsTrue(n1.ToString().Contains("OnCompleted"));
501         }
502 
503         [TestMethod]
OnCompleted_AcceptObserver()504         public void OnCompleted_AcceptObserver()
505         {
506             var obs = new CheckOnCompletedObserver();
507 
508             var n1 = Notification.CreateOnCompleted<int>();
509             n1.Accept(obs);
510 
511             Assert.IsTrue(obs.Completed);
512         }
513 
514         class CheckOnCompletedObserver : IObserver<int>
515         {
OnNext(int value)516             public void OnNext(int value)
517             {
518                 throw new NotImplementedException();
519             }
520 
521             public bool Completed { get; private set; }
522 
OnError(Exception exception)523             public void OnError(Exception exception)
524             {
525                 throw new NotImplementedException();
526             }
527 
OnCompleted()528             public void OnCompleted()
529             {
530                 Completed = true;
531             }
532         }
533 
534         [TestMethod]
OnCompleted_AcceptObserverWithResult()535         public void OnCompleted_AcceptObserverWithResult()
536         {
537             var n1 = Notification.CreateOnCompleted<int>();
538             var res = n1.Accept(new AcceptObserver(x => { Assert.Fail(); return null; }, _ => { Assert.Fail(); return null; }, () => "OK"));
539 
540             Assert.AreEqual("OK", res);
541         }
542 
543         [TestMethod]
OnCompleted_AcceptObserverWithResult_Null()544         public void OnCompleted_AcceptObserverWithResult_Null()
545         {
546             var n1 = Notification.CreateOnCompleted<int>();
547             ReactiveAssert.Throws<ArgumentNullException>(() => n1.Accept(default(IObserver<int, string>)));
548         }
549 
550         [TestMethod]
OnCompleted_AcceptAction()551         public void OnCompleted_AcceptAction()
552         {
553             var obs = false;
554 
555             var n1 = Notification.CreateOnCompleted<int>();
556             n1.Accept(x => { Assert.Fail(); }, _ => { Assert.Fail(); }, () => { obs = true; });
557 
558             Assert.IsTrue(obs);
559         }
560 
561         [TestMethod]
OnCompleted_AcceptActionWithResult()562         public void OnCompleted_AcceptActionWithResult()
563         {
564             var n1 = Notification.CreateOnCompleted<int>();
565             var res = n1.Accept(x => { Assert.Fail(); return null; }, _ => { Assert.Fail(); return null; }, () => "OK");
566 
567             Assert.AreEqual("OK", res);
568         }
569 
570         class AcceptObserver : IObserver<int, string>
571         {
572             private Func<int, string> _onNext;
573             private Func<Exception, string> _onError;
574             private Func<string> _onCompleted;
575 
AcceptObserver(Func<int, string> onNext, Func<Exception, string> onError, Func<string> onCompleted)576             public AcceptObserver(Func<int, string> onNext, Func<Exception, string> onError, Func<string> onCompleted)
577             {
578                 _onNext = onNext;
579                 _onError = onError;
580                 _onCompleted = onCompleted;
581             }
582 
OnNext(int value)583             public string OnNext(int value)
584             {
585                 return _onNext(value);
586             }
587 
OnError(Exception exception)588             public string OnError(Exception exception)
589             {
590                 return _onError(exception);
591             }
592 
OnCompleted()593             public string OnCompleted()
594             {
595                 return _onCompleted();
596             }
597         }
598     }
599 }
600