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