a575963da9
Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
400 lines
14 KiB
C#
400 lines
14 KiB
C#
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
|
|
|
using System;
|
|
using System.Reactive;
|
|
using System.Reactive.Concurrency;
|
|
using System.Reactive.Linq;
|
|
using System.Threading;
|
|
using Microsoft.Reactive.Testing;
|
|
#if NUNIT
|
|
using NUnit.Framework;
|
|
using TestClassAttribute = NUnit.Framework.TestFixtureAttribute;
|
|
using TestMethodAttribute = NUnit.Framework.TestAttribute;
|
|
using TestInitializeAttribute = NUnit.Framework.SetUpAttribute;
|
|
#else
|
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
|
#endif
|
|
using System.Collections.Generic;
|
|
|
|
namespace ReactiveTests.Tests
|
|
{
|
|
[TestClass]
|
|
public partial class ObservableExtensionsTest : ReactiveTest
|
|
{
|
|
#region Subscribe
|
|
|
|
[TestMethod]
|
|
public void Subscribe_ArgumentChecking()
|
|
{
|
|
var someObservable = Observable.Empty<int>();
|
|
|
|
ReactiveAssert.Throws<ArgumentNullException>(() => ObservableExtensions.Subscribe<int>(default(IObservable<int>)));
|
|
|
|
ReactiveAssert.Throws<ArgumentNullException>(() => ObservableExtensions.Subscribe<int>(default(IObservable<int>), _ => { }));
|
|
ReactiveAssert.Throws<ArgumentNullException>(() => ObservableExtensions.Subscribe<int>(someObservable, default(Action<int>)));
|
|
|
|
ReactiveAssert.Throws<ArgumentNullException>(() => ObservableExtensions.Subscribe<int>(default(IObservable<int>), _ => { }, () => { }));
|
|
ReactiveAssert.Throws<ArgumentNullException>(() => ObservableExtensions.Subscribe<int>(someObservable, default(Action<int>), () => { }));
|
|
ReactiveAssert.Throws<ArgumentNullException>(() => ObservableExtensions.Subscribe<int>(someObservable, _ => { }, default(Action)));
|
|
|
|
ReactiveAssert.Throws<ArgumentNullException>(() => ObservableExtensions.Subscribe<int>(default(IObservable<int>), _ => { }, (Exception _) => { }));
|
|
ReactiveAssert.Throws<ArgumentNullException>(() => ObservableExtensions.Subscribe<int>(someObservable, default(Action<int>), (Exception _) => { }));
|
|
ReactiveAssert.Throws<ArgumentNullException>(() => ObservableExtensions.Subscribe<int>(someObservable, _ => { }, default(Action<Exception>)));
|
|
|
|
ReactiveAssert.Throws<ArgumentNullException>(() => ObservableExtensions.Subscribe<int>(default(IObservable<int>), _ => { }, (Exception _) => { }, () => { }));
|
|
ReactiveAssert.Throws<ArgumentNullException>(() => ObservableExtensions.Subscribe<int>(someObservable, default(Action<int>), (Exception _) => { }, () => { }));
|
|
ReactiveAssert.Throws<ArgumentNullException>(() => ObservableExtensions.Subscribe<int>(someObservable, _ => { }, default(Action<Exception>), () => { }));
|
|
ReactiveAssert.Throws<ArgumentNullException>(() => ObservableExtensions.Subscribe<int>(someObservable, _ => { }, (Exception _) => { }, default(Action)));
|
|
}
|
|
|
|
[TestMethod]
|
|
public void Subscribe_None_Return()
|
|
{
|
|
Observable.Return(1, Scheduler.Immediate).Subscribe();
|
|
}
|
|
|
|
[TestMethod]
|
|
public void Subscribe_None_Throw()
|
|
{
|
|
var ex = new Exception();
|
|
|
|
var xs = Observable.Throw<int>(ex, Scheduler.Immediate);
|
|
|
|
ReactiveAssert.Throws(ex, () => xs.Subscribe());
|
|
}
|
|
|
|
[TestMethod]
|
|
public void Subscribe_None_Empty()
|
|
{
|
|
Observable.Empty<int>(Scheduler.Immediate).Subscribe((int _) => { Assert.Fail(); });
|
|
}
|
|
|
|
[TestMethod]
|
|
public void Subscribe_OnNext_Return()
|
|
{
|
|
int _x = -1;
|
|
Observable.Return(42, Scheduler.Immediate).Subscribe((int x) => { _x = x; });
|
|
Assert.AreEqual(42, _x);
|
|
}
|
|
|
|
[TestMethod]
|
|
public void Subscribe_OnNext_Throw()
|
|
{
|
|
var ex = new Exception();
|
|
|
|
var xs = Observable.Throw<int>(ex, Scheduler.Immediate);
|
|
|
|
ReactiveAssert.Throws(ex, () => xs.Subscribe(_ => { Assert.Fail(); }));
|
|
}
|
|
|
|
[TestMethod]
|
|
public void Subscribe_OnNext_Empty()
|
|
{
|
|
Observable.Empty<int>(Scheduler.Immediate).Subscribe((int _) => { Assert.Fail(); });
|
|
}
|
|
|
|
[TestMethod]
|
|
public void Subscribe_OnNextOnCompleted_Return()
|
|
{
|
|
bool finished = false;
|
|
int _x = -1;
|
|
Observable.Return(42, Scheduler.Immediate).Subscribe((int x) => { _x = x; }, () => { finished = true; });
|
|
Assert.AreEqual(42, _x);
|
|
Assert.IsTrue(finished);
|
|
}
|
|
|
|
[TestMethod]
|
|
public void Subscribe_OnNextOnCompleted_Throw()
|
|
{
|
|
var ex = new Exception();
|
|
|
|
var xs = Observable.Throw<int>(ex, Scheduler.Immediate);
|
|
|
|
ReactiveAssert.Throws(ex, () => xs.Subscribe(_ => { Assert.Fail(); }, () => { Assert.Fail(); }));
|
|
}
|
|
|
|
[TestMethod]
|
|
public void Subscribe_OnNextOnCompleted_Empty()
|
|
{
|
|
bool finished = false;
|
|
Observable.Empty<int>(Scheduler.Immediate).Subscribe((int _) => { Assert.Fail(); }, () => { finished = true; });
|
|
Assert.IsTrue(finished);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Subscribe with CancellationToken
|
|
|
|
#if !NO_TPL
|
|
|
|
[TestMethod]
|
|
public void Subscribe_CT_ArgumentChecking()
|
|
{
|
|
var someObservable = Observable.Empty<int>();
|
|
var someObserver = Observer.Create<int>(_ => { });
|
|
var ct = CancellationToken.None;
|
|
|
|
ReactiveAssert.Throws<ArgumentNullException>(() => ObservableExtensions.Subscribe<int>(default(IObservable<int>), someObserver, ct));
|
|
ReactiveAssert.Throws<ArgumentNullException>(() => ObservableExtensions.Subscribe<int>(someObservable, default(IObserver<int>), ct));
|
|
|
|
ReactiveAssert.Throws<ArgumentNullException>(() => ObservableExtensions.Subscribe<int>(default(IObservable<int>), ct));
|
|
|
|
ReactiveAssert.Throws<ArgumentNullException>(() => ObservableExtensions.Subscribe<int>(default(IObservable<int>), _ => { }, ct));
|
|
ReactiveAssert.Throws<ArgumentNullException>(() => ObservableExtensions.Subscribe<int>(someObservable, default(Action<int>), ct));
|
|
|
|
ReactiveAssert.Throws<ArgumentNullException>(() => ObservableExtensions.Subscribe<int>(default(IObservable<int>), _ => { }, () => { }, ct));
|
|
ReactiveAssert.Throws<ArgumentNullException>(() => ObservableExtensions.Subscribe<int>(someObservable, default(Action<int>), () => { }, ct));
|
|
ReactiveAssert.Throws<ArgumentNullException>(() => ObservableExtensions.Subscribe<int>(someObservable, _ => { }, default(Action), ct));
|
|
|
|
ReactiveAssert.Throws<ArgumentNullException>(() => ObservableExtensions.Subscribe<int>(default(IObservable<int>), _ => { }, (Exception _) => { }, ct));
|
|
ReactiveAssert.Throws<ArgumentNullException>(() => ObservableExtensions.Subscribe<int>(someObservable, default(Action<int>), (Exception _) => { }, ct));
|
|
ReactiveAssert.Throws<ArgumentNullException>(() => ObservableExtensions.Subscribe<int>(someObservable, _ => { }, default(Action<Exception>), ct));
|
|
|
|
ReactiveAssert.Throws<ArgumentNullException>(() => ObservableExtensions.Subscribe<int>(default(IObservable<int>), _ => { }, (Exception _) => { }, () => { }, ct));
|
|
ReactiveAssert.Throws<ArgumentNullException>(() => ObservableExtensions.Subscribe<int>(someObservable, default(Action<int>), (Exception _) => { }, () => { }, ct));
|
|
ReactiveAssert.Throws<ArgumentNullException>(() => ObservableExtensions.Subscribe<int>(someObservable, _ => { }, default(Action<Exception>), () => { }, ct));
|
|
ReactiveAssert.Throws<ArgumentNullException>(() => ObservableExtensions.Subscribe<int>(someObservable, _ => { }, (Exception _) => { }, default(Action), ct));
|
|
}
|
|
|
|
[TestMethod]
|
|
public void Subscribe_CT_None()
|
|
{
|
|
var scheduler = new TestScheduler();
|
|
|
|
var xs = scheduler.CreateHotObservable(
|
|
OnNext(210, 1),
|
|
OnNext(220, 2),
|
|
OnNext(230, 3),
|
|
OnCompleted<int>(240)
|
|
);
|
|
|
|
var obs = scheduler.CreateObserver<int>();
|
|
|
|
scheduler.ScheduleAbsolute(200, () => xs.Subscribe(obs, CancellationToken.None));
|
|
|
|
scheduler.Start();
|
|
|
|
obs.Messages.AssertEqual(
|
|
OnNext(210, 1),
|
|
OnNext(220, 2),
|
|
OnNext(230, 3),
|
|
OnCompleted<int>(240)
|
|
);
|
|
|
|
xs.Subscriptions.AssertEqual(
|
|
Subscribe(200, Subscription.Infinite /* no auto-dispose when using CreateHotObservable */)
|
|
);
|
|
}
|
|
|
|
[TestMethod]
|
|
public void Subscribe_CT_CancelBeforeBegin()
|
|
{
|
|
var scheduler = new TestScheduler();
|
|
|
|
var xs = scheduler.CreateHotObservable(
|
|
OnNext(210, 1),
|
|
OnNext(220, 2),
|
|
OnNext(230, 3),
|
|
OnCompleted<int>(240)
|
|
);
|
|
|
|
var cts = new CancellationTokenSource();
|
|
|
|
var obs = scheduler.CreateObserver<int>();
|
|
|
|
scheduler.ScheduleAbsolute(200, () => xs.Subscribe(obs, cts.Token));
|
|
scheduler.ScheduleAbsolute(150, cts.Cancel);
|
|
|
|
scheduler.Start();
|
|
|
|
obs.Messages.AssertEqual(
|
|
);
|
|
|
|
xs.Subscriptions.AssertEqual(
|
|
);
|
|
}
|
|
|
|
[TestMethod]
|
|
public void Subscribe_CT_CancelMiddle()
|
|
{
|
|
var scheduler = new TestScheduler();
|
|
|
|
var xs = scheduler.CreateHotObservable(
|
|
OnNext(210, 1),
|
|
OnNext(220, 2),
|
|
OnNext(230, 3),
|
|
OnCompleted<int>(240)
|
|
);
|
|
|
|
var cts = new CancellationTokenSource();
|
|
|
|
var obs = scheduler.CreateObserver<int>();
|
|
|
|
scheduler.ScheduleAbsolute(200, () => xs.Subscribe(obs, cts.Token));
|
|
scheduler.ScheduleAbsolute(225, cts.Cancel);
|
|
|
|
scheduler.Start();
|
|
|
|
obs.Messages.AssertEqual(
|
|
OnNext(210, 1),
|
|
OnNext(220, 2)
|
|
);
|
|
|
|
xs.Subscriptions.AssertEqual(
|
|
Subscribe(200, 225)
|
|
);
|
|
}
|
|
|
|
[TestMethod]
|
|
public void Subscribe_CT_CancelAfterEnd()
|
|
{
|
|
var scheduler = new TestScheduler();
|
|
|
|
var ex = new Exception();
|
|
|
|
var xs = scheduler.CreateHotObservable(
|
|
OnNext(210, 1),
|
|
OnNext(220, 2),
|
|
OnNext(230, 3),
|
|
OnError<int>(240, ex)
|
|
);
|
|
|
|
var cts = new CancellationTokenSource();
|
|
|
|
var obs = scheduler.CreateObserver<int>();
|
|
|
|
scheduler.ScheduleAbsolute(200, () => xs.Subscribe(obs, cts.Token));
|
|
scheduler.ScheduleAbsolute(250, cts.Cancel);
|
|
|
|
scheduler.Start();
|
|
|
|
obs.Messages.AssertEqual(
|
|
OnNext(210, 1),
|
|
OnNext(220, 2),
|
|
OnNext(230, 3),
|
|
OnError<int>(240, ex)
|
|
);
|
|
|
|
xs.Subscriptions.AssertEqual(
|
|
Subscribe(200, Subscription.Infinite /* no auto-dispose when using CreateHotObservable */)
|
|
);
|
|
}
|
|
|
|
[TestMethod]
|
|
public void Subscribe_CT_NeverCancel()
|
|
{
|
|
var scheduler = new TestScheduler();
|
|
|
|
var xs = scheduler.CreateHotObservable(
|
|
OnNext(210, 1),
|
|
OnNext(220, 2),
|
|
OnNext(230, 3),
|
|
OnCompleted<int>(240)
|
|
);
|
|
|
|
var cts = new CancellationTokenSource();
|
|
|
|
var obs = scheduler.CreateObserver<int>();
|
|
|
|
scheduler.ScheduleAbsolute(200, () => xs.Subscribe(obs, cts.Token));
|
|
|
|
scheduler.Start();
|
|
|
|
obs.Messages.AssertEqual(
|
|
OnNext(210, 1),
|
|
OnNext(220, 2),
|
|
OnNext(230, 3),
|
|
OnCompleted<int>(240)
|
|
);
|
|
|
|
xs.Subscriptions.AssertEqual(
|
|
Subscribe(200, Subscription.Infinite /* no auto-dispose when using CreateHotObservable */)
|
|
);
|
|
}
|
|
|
|
[TestMethod]
|
|
public void Subscribe_CT_Overloads_AlreadyCancelled()
|
|
{
|
|
var xs = Observable.Defer<int>(() =>
|
|
{
|
|
Assert.Fail();
|
|
return Observable.Return(42, Scheduler.Immediate);
|
|
});
|
|
|
|
var cts = new CancellationTokenSource();
|
|
cts.Cancel();
|
|
|
|
xs.Subscribe(cts.Token);
|
|
xs.Subscribe(_ => { }, cts.Token);
|
|
xs.Subscribe(_ => { }, ex => { }, cts.Token);
|
|
xs.Subscribe(_ => { }, () => { }, cts.Token);
|
|
xs.Subscribe(_ => { }, ex => { }, () => { }, cts.Token);
|
|
xs.Subscribe(Observer.Create<int>(_ => { }, ex => { }, () => { }), cts.Token);
|
|
}
|
|
|
|
[TestMethod]
|
|
public void Subscribe_CT_Overloads_None()
|
|
{
|
|
var i = 0;
|
|
var n = 0;
|
|
var e = 0;
|
|
var c = 0;
|
|
|
|
var xs = Observable.Defer<int>(() =>
|
|
{
|
|
i++;
|
|
return Observable.Return(42, Scheduler.Immediate);
|
|
});
|
|
|
|
xs.Subscribe(CancellationToken.None);
|
|
xs.Subscribe(_ => { n++; }, CancellationToken.None);
|
|
xs.Subscribe(_ => { n++; }, ex => { e++; }, CancellationToken.None);
|
|
xs.Subscribe(_ => { n++; }, () => { c++; }, CancellationToken.None);
|
|
xs.Subscribe(_ => { n++; }, ex => { e++; }, () => { c++; }, CancellationToken.None);
|
|
xs.Subscribe(Observer.Create<int>(_ => { n++; }, ex => { e++; }, () => { c++; }), CancellationToken.None);
|
|
|
|
Assert.AreEqual(6, i);
|
|
Assert.AreEqual(5, n);
|
|
Assert.AreEqual(0, e);
|
|
Assert.AreEqual(3, c);
|
|
}
|
|
|
|
[TestMethod]
|
|
public void Subscribe_CT_CancelDuringCallback()
|
|
{
|
|
var scheduler = new TestScheduler();
|
|
|
|
var xs = scheduler.CreateHotObservable(
|
|
OnNext(210, 1),
|
|
OnNext(220, 2),
|
|
OnNext(230, 3),
|
|
OnCompleted<int>(240)
|
|
);
|
|
|
|
var cts = new CancellationTokenSource();
|
|
|
|
var n = 0;
|
|
|
|
scheduler.ScheduleAbsolute(200, () => xs.Subscribe(x =>
|
|
{
|
|
n++;
|
|
|
|
if (x == 2)
|
|
cts.Cancel();
|
|
}, cts.Token));
|
|
|
|
scheduler.Start();
|
|
|
|
Assert.AreEqual(2, n);
|
|
|
|
xs.Subscriptions.AssertEqual(
|
|
Subscribe(200, 220)
|
|
);
|
|
}
|
|
|
|
#endif
|
|
|
|
#endregion
|
|
}
|
|
}
|