Imported Upstream version 3.6.0

Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
This commit is contained in:
Jo Shields
2014-08-13 10:39:27 +01:00
commit a575963da9
50588 changed files with 8155799 additions and 0 deletions

View File

@@ -0,0 +1,140 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
#if !SILVERLIGHT // MethodAccessException
using System;
using System.Reactive.Concurrency;
using System.Reflection;
#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
namespace ReactiveTests.Tests
{
[TestClass]
public class AsyncLockTest
{
[TestMethod, ExpectedException(typeof(ArgumentNullException))]
public void Wait_ArgumentChecking()
{
var asyncLock = new AsyncLock();
asyncLock.Wait(null);
}
[TestMethod]
public void Wait_Graceful()
{
var ok = false;
new AsyncLock().Wait(() => { ok = true; });
Assert.IsTrue(ok);
}
[TestMethod]
public void Wait_Fail()
{
var l = new AsyncLock();
var ex = new Exception();
try
{
l.Wait(() => { throw ex; });
Assert.Fail();
}
catch (Exception e)
{
Assert.AreSame(ex, e);
}
// has faulted; should not run
l.Wait(() => { Assert.Fail(); });
}
[TestMethod]
public void Wait_QueuesWork()
{
var l = new AsyncLock();
var l1 = false;
var l2 = false;
l.Wait(() => { l.Wait(() => { Assert.IsTrue(l1); l2 = true; }); l1 = true; });
Assert.IsTrue(l2);
}
[TestMethod]
public void Dispose()
{
var l = new AsyncLock();
var l1 = false;
var l2 = false;
var l3 = false;
var l4 = false;
l.Wait(() =>
{
l.Wait(() =>
{
l.Wait(() =>
{
l3 = true;
});
l2 = true;
l.Dispose();
l.Wait(() =>
{
l4 = true;
});
});
l1 = true;
});
Assert.IsTrue(l1);
Assert.IsTrue(l2);
Assert.IsFalse(l3);
Assert.IsFalse(l4);
}
public class AsyncLock
{
object instance;
public AsyncLock()
{
instance = typeof(Scheduler).Assembly.GetType("System.Reactive.Concurrency.AsyncLock").GetConstructor(new Type[] { }).Invoke(new object[] { });
}
public void Wait(Action action)
{
try
{
instance.GetType().GetMethod("Wait").Invoke(instance, new object[] { action });
}
catch (TargetInvocationException ex)
{
throw ex.InnerException;
}
}
public void Dispose()
{
try
{
instance.GetType().GetMethod("Dispose").Invoke(instance, new object[0]);
}
catch (TargetInvocationException ex)
{
throw ex.InnerException;
}
}
}
}
}
#endif

View File

@@ -0,0 +1,98 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using System;
using System.Reactive.Concurrency;
using System.Threading;
#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
namespace ReactiveTests.Tests
{
[TestClass]
public class ConcurrencyTest
{
[TestMethod]
public void CurrentScheduler_EnsureTrampoline()
{
const int concurrency = 100;
var passed = true;
var s = new Semaphore(0, int.MaxValue);
var e = new ManualResetEvent(false);
for (var i = 0; i < concurrency; ++i)
NewThreadScheduler.Default.Schedule(() =>
{
e.WaitOne();
try
{
if (Scheduler.CurrentThread.ScheduleRequired)
Scheduler.CurrentThread.Schedule(() => { });
else
new Action(() => { })();
}
catch (NullReferenceException)
{
passed = false;
}
finally
{
s.Release();
}
});
e.Set();
for (var i = 0; i < concurrency; ++i)
s.WaitOne();
Assert.IsTrue(passed);
}
[TestMethod]
public void CurrentScheduler_Schedule()
{
const int concurrency = 100;
var passed = true;
var s = new Semaphore(0, int.MaxValue);
var e = new ManualResetEvent(false);
for (var i = 0; i < concurrency; ++i)
NewThreadScheduler.Default.Schedule(() =>
{
e.WaitOne();
try
{
if (Scheduler.CurrentThread.ScheduleRequired)
Scheduler.CurrentThread.Schedule(() => { });
else
new Action(() => { })();
}
catch (NullReferenceException)
{
passed = false;
}
finally
{
s.Release();
}
});
e.Set();
for (var i = 0; i < concurrency; ++i)
s.WaitOne();
Assert.IsTrue(passed);
}
}
}

View File

@@ -0,0 +1,336 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
#if HAS_WINFORMS
using System;
using System.Reactive.Concurrency;
using System.Reactive.Disposables;
using System.Diagnostics;
using System.Threading;
using System.Windows.Forms;
#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 Microsoft.Reactive.Testing;
namespace ReactiveTests.Tests
{
[TestClass]
public class ControlSchedulerTest
{
[TestMethod]
public void Ctor_ArgumentChecking()
{
ReactiveAssert.Throws<ArgumentNullException>(() => new ControlScheduler(null));
}
[TestMethod]
public void Control()
{
var lbl = new Label();
Assert.AreSame(lbl, new ControlScheduler(lbl).Control);
}
[TestMethod]
public void Now()
{
var res = new ControlScheduler(new Label()).Now - DateTime.Now;
Assert.IsTrue(res.Seconds < 1);
}
[TestMethod]
public void Schedule_ArgumentChecking()
{
var s = new ControlScheduler(new Label());
ReactiveAssert.Throws<ArgumentNullException>(() => s.Schedule(42, default(Func<IScheduler, int, IDisposable>)));
ReactiveAssert.Throws<ArgumentNullException>(() => s.Schedule(42, TimeSpan.FromSeconds(1), default(Func<IScheduler, int, IDisposable>)));
ReactiveAssert.Throws<ArgumentNullException>(() => s.Schedule(42, DateTimeOffset.Now, default(Func<IScheduler, int, IDisposable>)));
}
[TestMethod]
public void Schedule()
{
var evt = new ManualResetEvent(false);
var id = Thread.CurrentThread.ManagedThreadId;
var lbl = CreateLabel();
var sch = new ControlScheduler(lbl);
sch.Schedule(() => { lbl.Text = "Okay"; Assert.AreNotEqual(id, Thread.CurrentThread.ManagedThreadId); });
sch.Schedule(() => { Assert.AreEqual("Okay", lbl.Text); Assert.AreNotEqual(id, Thread.CurrentThread.ManagedThreadId); evt.Set(); });
evt.WaitOne();
Application.Exit();
}
[TestMethod]
public void ScheduleError()
{
var evt = new ManualResetEvent(false);
var ex = new Exception();
var lbl = CreateLabelWithHandler(e => {
Assert.AreSame(ex, e);
evt.Set();
});
var sch = new ControlScheduler(lbl);
sch.Schedule(() => { throw ex; });
evt.WaitOne();
Application.Exit();
}
[TestMethod]
public void ScheduleRelative()
{
ScheduleRelative_(TimeSpan.FromSeconds(0.1));
}
[TestMethod]
public void ScheduleRelative_Zero()
{
ScheduleRelative_(TimeSpan.Zero);
}
private void ScheduleRelative_(TimeSpan delay)
{
var evt = new ManualResetEvent(false);
var id = Thread.CurrentThread.ManagedThreadId;
var lbl = CreateLabel();
var sch = new ControlScheduler(lbl);
sch.Schedule(delay, () =>
{
lbl.Text = "Okay";
Assert.AreNotEqual(id, Thread.CurrentThread.ManagedThreadId);
sch.Schedule(() =>
{
Assert.AreEqual("Okay", lbl.Text);
Assert.AreNotEqual(id, Thread.CurrentThread.ManagedThreadId);
evt.Set();
});
});
evt.WaitOne();
Application.Exit();
}
[TestMethod]
public void ScheduleRelative_Nested()
{
var evt = new ManualResetEvent(false);
var id = Thread.CurrentThread.ManagedThreadId;
var lbl = CreateLabel();
var sch = new ControlScheduler(lbl);
sch.Schedule(TimeSpan.FromSeconds(0.1), () =>
{
sch.Schedule(TimeSpan.FromSeconds(0.1), () =>
{
lbl.Text = "Okay";
Assert.AreNotEqual(id, Thread.CurrentThread.ManagedThreadId);
sch.Schedule(() =>
{
Assert.AreEqual("Okay", lbl.Text);
Assert.AreNotEqual(id, Thread.CurrentThread.ManagedThreadId);
evt.Set();
});
});
});
evt.WaitOne();
Application.Exit();
}
[TestMethod]
public void ScheduleRelative_Cancel()
{
var evt = new ManualResetEvent(false);
var id = Thread.CurrentThread.ManagedThreadId;
var lbl = CreateLabel();
var sch = new ControlScheduler(lbl);
sch.Schedule(TimeSpan.FromSeconds(0.1), () =>
{
lbl.Text = "Okay";
Assert.AreNotEqual(id, Thread.CurrentThread.ManagedThreadId);
var d = sch.Schedule(TimeSpan.FromSeconds(0.1), () =>
{
lbl.Text = "Oops!";
});
sch.Schedule(() =>
{
d.Dispose();
});
sch.Schedule(TimeSpan.FromSeconds(0.2), () =>
{
Assert.AreEqual("Okay", lbl.Text);
Assert.AreNotEqual(id, Thread.CurrentThread.ManagedThreadId);
evt.Set();
});
});
evt.WaitOne();
Application.Exit();
}
[TestMethod]
public void SchedulePeriodic_ArgumentChecking()
{
var s = new ControlScheduler(new Label());
ReactiveAssert.Throws<ArgumentNullException>(() => s.SchedulePeriodic(42, TimeSpan.FromSeconds(1), default(Func<int, int>)));
ReactiveAssert.Throws<ArgumentOutOfRangeException>(() => s.SchedulePeriodic(42, TimeSpan.Zero, x => x));
ReactiveAssert.Throws<ArgumentOutOfRangeException>(() => s.SchedulePeriodic(42, TimeSpan.FromMilliseconds(1).Subtract(TimeSpan.FromTicks(1)), x => x));
}
[TestMethod]
public void SchedulePeriodic()
{
var evt = new ManualResetEvent(false);
var id = Thread.CurrentThread.ManagedThreadId;
var lbl = CreateLabel();
var sch = new ControlScheduler(lbl);
var d = new SingleAssignmentDisposable();
d.Disposable = sch.SchedulePeriodic(1, TimeSpan.FromSeconds(0.1), n =>
{
lbl.Text = "Okay " + n;
Assert.AreNotEqual(id, Thread.CurrentThread.ManagedThreadId);
if (n == 3)
{
d.Dispose();
sch.Schedule(TimeSpan.FromSeconds(0.2), () =>
{
Assert.AreEqual("Okay 3", lbl.Text);
Assert.AreNotEqual(id, Thread.CurrentThread.ManagedThreadId);
evt.Set();
});
}
if (n > 3)
{
Assert.Fail();
}
return n + 1;
});
evt.WaitOne();
Application.Exit();
}
[TestMethod]
public void SchedulePeriodic_Nested()
{
var evt = new ManualResetEvent(false);
var id = Thread.CurrentThread.ManagedThreadId;
var lbl = CreateLabel();
var sch = new ControlScheduler(lbl);
sch.Schedule(() =>
{
lbl.Text = "Okay";
var d = new SingleAssignmentDisposable();
d.Disposable = sch.SchedulePeriodic(1, TimeSpan.FromSeconds(0.1), n =>
{
lbl.Text = "Okay " + n;
Assert.AreNotEqual(id, Thread.CurrentThread.ManagedThreadId);
if (n == 3)
{
d.Dispose();
sch.Schedule(TimeSpan.FromSeconds(0.2), () =>
{
Assert.AreEqual("Okay 3", lbl.Text);
Assert.AreNotEqual(id, Thread.CurrentThread.ManagedThreadId);
evt.Set();
});
}
return n + 1;
});
});
evt.WaitOne();
Application.Exit();
}
private Label CreateLabel()
{
var loaded = new ManualResetEvent(false);
var lbl = default(Label);
var t = new Thread(() =>
{
lbl = new Label();
var frm = new Form { Controls = { lbl }, Width = 0, Height = 0, FormBorderStyle = FormBorderStyle.None, ShowInTaskbar = false };
frm.Load += (_, __) =>
{
loaded.Set();
};
Application.Run(frm);
});
t.SetApartmentState(ApartmentState.STA);
t.Start();
loaded.WaitOne();
return lbl;
}
private Label CreateLabelWithHandler(Action<Exception> handler)
{
var loaded = new ManualResetEvent(false);
var lbl = default(Label);
var t = new Thread(() =>
{
lbl = new Label();
var frm = new Form { Controls = { lbl }, Width = 0, Height = 0, FormBorderStyle = FormBorderStyle.None, ShowInTaskbar = false };
frm.Load += (_, __) =>
{
loaded.Set();
};
Application.ThreadException += (o, e) =>
{
handler(e.Exception);
};
Application.Run(frm);
});
t.SetApartmentState(ApartmentState.STA);
t.Start();
loaded.WaitOne();
return lbl;
}
}
}
#endif

View File

@@ -0,0 +1,185 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using System;
using System.Diagnostics;
using System.Reactive.Concurrency;
using System.Threading;
#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 Microsoft.Reactive.Testing;
namespace ReactiveTests.Tests
{
[TestClass]
public class CurrentThreadSchedulerTest
{
[TestMethod]
public void CurrentThread_ArgumentChecking()
{
ReactiveAssert.Throws<ArgumentNullException>(() => Scheduler.CurrentThread.Schedule(42, default(Func<IScheduler, int, IDisposable>)));
ReactiveAssert.Throws<ArgumentNullException>(() => Scheduler.CurrentThread.Schedule(42, default(TimeSpan), default(Func<IScheduler, int, IDisposable>)));
ReactiveAssert.Throws<ArgumentNullException>(() => Scheduler.CurrentThread.Schedule(42, default(DateTimeOffset), default(Func<IScheduler, int, IDisposable>)));
}
[TestMethod]
public void CurrentThread_Now()
{
var res = Scheduler.CurrentThread.Now - DateTime.Now;
Assert.IsTrue(res.Seconds < 1);
}
[TestMethod]
public void CurrentThread_ScheduleAction()
{
var id = Thread.CurrentThread.ManagedThreadId;
var ran = false;
Scheduler.CurrentThread.Schedule(() => { Assert.AreEqual(id, Thread.CurrentThread.ManagedThreadId); ran = true; });
Assert.IsTrue(ran);
}
[TestMethod]
public void CurrentThread_ScheduleActionError()
{
var ex = new Exception();
try
{
Scheduler.CurrentThread.Schedule(() => { throw ex; });
Assert.Fail();
}
catch (Exception e)
{
Assert.AreSame(e, ex);
}
}
[TestMethod]
public void CurrentThread_ScheduleActionNested()
{
var id = Thread.CurrentThread.ManagedThreadId;
var ran = false;
Scheduler.CurrentThread.Schedule(() => {
Assert.AreEqual(id, Thread.CurrentThread.ManagedThreadId);
Scheduler.CurrentThread.Schedule(() => { ran = true; });
});
Assert.IsTrue(ran);
}
[TestMethod]
public void CurrentThread_ScheduleActionNested_TimeSpan()
{
var id = Thread.CurrentThread.ManagedThreadId;
var ran = false;
Scheduler.CurrentThread.Schedule(() =>
{
Assert.AreEqual(id, Thread.CurrentThread.ManagedThreadId);
Scheduler.CurrentThread.Schedule(TimeSpan.FromSeconds(1), () => { ran = true; });
});
Assert.IsTrue(ran);
}
#if !SILVERLIGHT
[TestMethod]
[Ignore]
public void CurrentThread_ScheduleActionDue()
{
var id = Thread.CurrentThread.ManagedThreadId;
var ran = false;
var sw = new Stopwatch();
sw.Start();
Scheduler.CurrentThread.Schedule(TimeSpan.FromSeconds(0.2), () => { sw.Stop(); Assert.AreEqual(id, Thread.CurrentThread.ManagedThreadId); ran = true; });
Assert.IsTrue(ran, "ran");
Assert.IsTrue(sw.ElapsedMilliseconds > 180, "due " + sw.ElapsedMilliseconds);
}
[TestMethod]
[Ignore]
public void CurrentThread_ScheduleActionDueNested()
{
var id = Thread.CurrentThread.ManagedThreadId;
var ran = false;
var sw = new Stopwatch();
sw.Start();
Scheduler.CurrentThread.Schedule(TimeSpan.FromSeconds(0.2), () => {
sw.Stop();
Assert.AreEqual(id, Thread.CurrentThread.ManagedThreadId);
sw.Start();
Scheduler.CurrentThread.Schedule(TimeSpan.FromSeconds(0.2), () => {
sw.Stop();
ran = true;
});
});
Assert.IsTrue(ran, "ran");
Assert.IsTrue(sw.ElapsedMilliseconds > 380, "due " + sw.ElapsedMilliseconds);
}
#endif
[TestMethod]
public void CurrentThread_EnsureTrampoline()
{
var ran1 = false;
var ran2 = false;
Scheduler.CurrentThread.EnsureTrampoline(() => {
Scheduler.CurrentThread.Schedule(() => { ran1 = true; });
Scheduler.CurrentThread.Schedule(() => { ran2 = true; });
});
Assert.IsTrue(ran1);
Assert.IsTrue(ran2);
}
[TestMethod]
public void CurrentThread_EnsureTrampoline_Nested()
{
var ran1 = false;
var ran2 = false;
Scheduler.CurrentThread.EnsureTrampoline(() =>
{
Scheduler.CurrentThread.EnsureTrampoline(() => { ran1 = true; });
Scheduler.CurrentThread.EnsureTrampoline(() => { ran2 = true; });
});
Assert.IsTrue(ran1);
Assert.IsTrue(ran2);
}
[TestMethod]
public void CurrentThread_EnsureTrampolineAndCancel()
{
var ran1 = false;
var ran2 = false;
Scheduler.CurrentThread.EnsureTrampoline(() =>
{
Scheduler.CurrentThread.Schedule(() => {
ran1 = true;
var d = Scheduler.CurrentThread.Schedule(() => { ran2 = true; });
d.Dispose();
});
});
Assert.IsTrue(ran1);
Assert.IsFalse(ran2);
}
[TestMethod]
public void CurrentThread_EnsureTrampolineAndCancelTimed()
{
var ran1 = false;
var ran2 = false;
Scheduler.CurrentThread.EnsureTrampoline(() =>
{
Scheduler.CurrentThread.Schedule(() =>
{
ran1 = true;
var d = Scheduler.CurrentThread.Schedule(TimeSpan.FromSeconds(1), () => { ran2 = true; });
d.Dispose();
});
});
Assert.IsTrue(ran1);
Assert.IsFalse(ran2);
}
}
}

View File

@@ -0,0 +1,130 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using System;
using System.Reactive.Concurrency;
using System.Diagnostics;
using System.Threading;
#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 Microsoft.Reactive.Testing;
namespace ReactiveTests.Tests
{
[TestClass]
public class DefaultSchedulerTest
{
[TestMethod]
public void Schedule_ArgumentChecking()
{
ReactiveAssert.Throws<ArgumentNullException>(() => DefaultScheduler.Instance.Schedule<int>(42, default(Func<IScheduler, int, IDisposable>)));
ReactiveAssert.Throws<ArgumentNullException>(() => DefaultScheduler.Instance.Schedule<int>(42, DateTimeOffset.Now, default(Func<IScheduler, int, IDisposable>)));
ReactiveAssert.Throws<ArgumentNullException>(() => DefaultScheduler.Instance.Schedule<int>(42, TimeSpan.Zero, default(Func<IScheduler, int, IDisposable>)));
ReactiveAssert.Throws<ArgumentNullException>(() => DefaultScheduler.Instance.SchedulePeriodic(42, TimeSpan.FromSeconds(1), default(Func<int, int>)));
ReactiveAssert.Throws<ArgumentOutOfRangeException>(() => DefaultScheduler.Instance.SchedulePeriodic(42, TimeSpan.FromSeconds(-1), _ => _));
}
[TestMethod]
public void Get_Now()
{
var res = DefaultScheduler.Instance.Now - DateTime.Now;
Assert.IsTrue(res.Seconds < 1);
}
[TestMethod]
public void ScheduleAction()
{
var id = Thread.CurrentThread.ManagedThreadId;
var nt = DefaultScheduler.Instance;
var evt = new ManualResetEvent(false);
nt.Schedule(() => { Assert.AreNotEqual(id, Thread.CurrentThread.ManagedThreadId); evt.Set(); });
evt.WaitOne();
}
#if !SILVERLIGHT
[TestMethod]
public void ScheduleActionDue()
{
var id = Thread.CurrentThread.ManagedThreadId;
var nt = DefaultScheduler.Instance;
var evt = new ManualResetEvent(false);
nt.Schedule(TimeSpan.FromSeconds(0.2), () => { Assert.AreNotEqual(id, Thread.CurrentThread.ManagedThreadId); evt.Set(); });
evt.WaitOne();
}
#endif
[TestMethod]
public void ScheduleActionCancel()
{
var id = Thread.CurrentThread.ManagedThreadId;
var nt = DefaultScheduler.Instance;
var set = false;
var d = nt.Schedule(TimeSpan.FromSeconds(0.2), () => { Assert.Fail(); set = true; });
d.Dispose();
Thread.Sleep(400);
Assert.IsFalse(set);
}
[TestMethod]
public void Periodic_NonReentrant()
{
var n = 0;
var fail = false;
var d = DefaultScheduler.Instance.SchedulePeriodic(0, TimeSpan.FromMilliseconds(50), x =>
{
try
{
if (Interlocked.Increment(ref n) > 1) // Without an AsyncLock this would fail.
fail = true;
Thread.Sleep(100);
return x + 1;
}
finally
{
Interlocked.Decrement(ref n);
}
});
Thread.Sleep(500);
d.Dispose();
Assert.IsFalse(fail);
}
#if DESKTOPCLR
[TestMethod]
public void No_ThreadPool_Starvation_Dispose()
{
var bwt = default(int);
var bio = default(int);
ThreadPool.GetAvailableThreads(out bwt, out bio);
var N = Environment.ProcessorCount * 2;
for (int i = 0; i < N; i++)
{
var e = new ManualResetEvent(false);
var f = new ManualResetEvent(false);
var d = Scheduler.Default.Schedule(TimeSpan.FromMilliseconds(1), () => { e.Set(); f.WaitOne(); });
e.WaitOne();
d.Dispose();
f.Set();
}
var ewt = default(int);
var eio = default(int);
ThreadPool.GetAvailableThreads(out ewt, out eio);
Assert.IsFalse(bwt - ewt >= N);
}
#endif
}
}

View File

@@ -0,0 +1,270 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
#if !NO_WINDOWS_THREADING
using System;
using System.Diagnostics;
using System.Reactive.Concurrency;
using System.Reactive.Disposables;
using System.Threading;
using System.Windows.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
#if SILVERLIGHT && !SILVERLIGHTM7
using Microsoft.Silverlight.Testing;
#endif
namespace ReactiveTests.Tests
{
[TestClass]
public class DispatcherSchedulerTest : TestBase
{
[TestMethod]
public void Ctor_ArgumentChecking()
{
ReactiveAssert.Throws<ArgumentNullException>(() => new DispatcherScheduler(null));
}
[TestMethod]
public void Current()
{
var d = DispatcherHelpers.EnsureDispatcher();
var e = new ManualResetEvent(false);
d.BeginInvoke(() =>
{
var c = DispatcherScheduler.Current;
c.Schedule(() => { e.Set(); });
});
e.WaitOne();
}
[TestMethod]
public void Current_None()
{
var e = default(Exception);
var t = new Thread(() =>
{
try
{
var ignored = DispatcherScheduler.Current;
}
catch (Exception ex)
{
e = ex;
}
});
t.Start();
t.Join();
Assert.IsTrue(e != null && e is InvalidOperationException);
}
[TestMethod]
public void Dispatcher()
{
var disp = DispatcherHelpers.EnsureDispatcher();
Assert.AreSame(disp.Dispatcher, new DispatcherScheduler(disp).Dispatcher);
}
[TestMethod]
public void Now()
{
var disp = DispatcherHelpers.EnsureDispatcher();
var res = new DispatcherScheduler(disp).Now - DateTime.Now;
Assert.IsTrue(res.Seconds < 1);
}
[TestMethod]
public void Schedule_ArgumentChecking()
{
var disp = DispatcherHelpers.EnsureDispatcher();
var s = new DispatcherScheduler(disp);
ReactiveAssert.Throws<ArgumentNullException>(() => s.Schedule(42, default(Func<IScheduler, int, IDisposable>)));
ReactiveAssert.Throws<ArgumentNullException>(() => s.Schedule(42, TimeSpan.FromSeconds(1), default(Func<IScheduler, int, IDisposable>)));
ReactiveAssert.Throws<ArgumentNullException>(() => s.Schedule(42, DateTimeOffset.Now, default(Func<IScheduler, int, IDisposable>)));
}
[TestMethod]
[Asynchronous]
public void Schedule()
{
var disp = DispatcherHelpers.EnsureDispatcher();
RunAsync(evt =>
{
var id = Thread.CurrentThread.ManagedThreadId;
var sch = new DispatcherScheduler(disp);
sch.Schedule(() =>
{
#if SILVERLIGHT
Assert.AreEqual(id, Thread.CurrentThread.ManagedThreadId); // Single-threaded test framework
#else
Assert.AreNotEqual(id, Thread.CurrentThread.ManagedThreadId);
#endif
disp.InvokeShutdown();
evt.Set();
});
});
}
#if !USE_SL_DISPATCHER
[TestMethod]
public void ScheduleError()
{
var ex = new Exception();
var id = Thread.CurrentThread.ManagedThreadId;
var disp = DispatcherHelpers.EnsureDispatcher();
var evt = new ManualResetEvent(false);
disp.UnhandledException += (o, e) =>
{
#if DESKTOPCLR40 || DESKTOPCLR45
Assert.AreSame(ex, e.Exception); // CHECK
#else
Assert.AreSame(ex, e.Exception.InnerException); // CHECK
#endif
evt.Set();
e.Handled = true;
};
var sch = new DispatcherScheduler(disp);
sch.Schedule(() => { throw ex; });
evt.WaitOne();
disp.InvokeShutdown();
}
[TestMethod]
public void ScheduleRelative()
{
ScheduleRelative_(TimeSpan.FromSeconds(0.2));
}
[TestMethod]
public void ScheduleRelative_Zero()
{
ScheduleRelative_(TimeSpan.Zero);
}
private void ScheduleRelative_(TimeSpan delay)
{
var evt = new ManualResetEvent(false);
var id = Thread.CurrentThread.ManagedThreadId;
var disp = DispatcherHelpers.EnsureDispatcher();
var sch = new DispatcherScheduler(disp);
sch.Schedule(delay, () =>
{
Assert.AreNotEqual(id, Thread.CurrentThread.ManagedThreadId);
sch.Schedule(delay, () =>
{
Assert.AreNotEqual(id, Thread.CurrentThread.ManagedThreadId);
evt.Set();
});
});
evt.WaitOne();
disp.InvokeShutdown();
}
[TestMethod]
public void ScheduleRelative_Cancel()
{
var evt = new ManualResetEvent(false);
var id = Thread.CurrentThread.ManagedThreadId;
var disp = DispatcherHelpers.EnsureDispatcher();
var sch = new DispatcherScheduler(disp);
sch.Schedule(TimeSpan.FromSeconds(0.1), () =>
{
Assert.AreNotEqual(id, Thread.CurrentThread.ManagedThreadId);
var d = sch.Schedule(TimeSpan.FromSeconds(0.1), () =>
{
Assert.Fail();
evt.Set();
});
sch.Schedule(() =>
{
d.Dispose();
});
sch.Schedule(TimeSpan.FromSeconds(0.2), () =>
{
Assert.AreNotEqual(id, Thread.CurrentThread.ManagedThreadId);
evt.Set();
});
});
evt.WaitOne();
disp.InvokeShutdown();
}
[TestMethod]
public void SchedulePeriodic_ArgumentChecking()
{
var disp = DispatcherHelpers.EnsureDispatcher();
var s = new DispatcherScheduler(disp);
ReactiveAssert.Throws<ArgumentNullException>(() => s.SchedulePeriodic(42, TimeSpan.FromSeconds(1), default(Func<int, int>)));
ReactiveAssert.Throws<ArgumentOutOfRangeException>(() => s.SchedulePeriodic(42, TimeSpan.FromSeconds(-1), x => x));
}
[TestMethod]
public void SchedulePeriodic()
{
var evt = new ManualResetEvent(false);
var id = Thread.CurrentThread.ManagedThreadId;
var disp = DispatcherHelpers.EnsureDispatcher();
var sch = new DispatcherScheduler(disp);
var d = new SingleAssignmentDisposable();
d.Disposable = sch.SchedulePeriodic(1, TimeSpan.FromSeconds(0.1), n =>
{
Assert.AreNotEqual(id, Thread.CurrentThread.ManagedThreadId);
if (n == 3)
{
d.Dispose();
sch.Schedule(TimeSpan.FromSeconds(0.2), () =>
{
Assert.AreNotEqual(id, Thread.CurrentThread.ManagedThreadId);
evt.Set();
});
}
if (n > 3)
{
Assert.Fail();
}
return n + 1;
});
evt.WaitOne();
disp.InvokeShutdown();
}
#endif
}
}
#endif

View File

@@ -0,0 +1,392 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reactive.Concurrency;
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
#if STRESS
using ReactiveTests.Stress.Schedulers;
#endif
namespace ReactiveTests.Tests
{
[TestClass]
public class EventLoopSchedulerTest
{
[TestMethod]
public void EventLoop_ArgumentChecking()
{
var el = new EventLoopScheduler();
ReactiveAssert.Throws<ArgumentNullException>(() => new EventLoopScheduler(null));
ReactiveAssert.Throws<ArgumentNullException>(() => el.Schedule<int>(42, default(Func<IScheduler, int, IDisposable>)));
ReactiveAssert.Throws<ArgumentNullException>(() => el.Schedule<int>(42, DateTimeOffset.Now, default(Func<IScheduler, int, IDisposable>)));
ReactiveAssert.Throws<ArgumentNullException>(() => el.Schedule<int>(42, TimeSpan.Zero, default(Func<IScheduler, int, IDisposable>)));
ReactiveAssert.Throws<ArgumentNullException>(() => el.SchedulePeriodic(42, TimeSpan.FromSeconds(1), default(Func<int, int>)));
ReactiveAssert.Throws<ArgumentOutOfRangeException>(() => el.SchedulePeriodic(42, TimeSpan.FromSeconds(-1), _ => _));
}
[TestMethod]
public void EventLoop_Now()
{
var res = new EventLoopScheduler().Now - DateTime.Now;
Assert.IsTrue(res.Seconds < 1);
}
[TestMethod]
public void EventLoop_ScheduleAction()
{
var ran = false;
var gate = new Semaphore(0, 1);
var el = new EventLoopScheduler();
el.Schedule(() => { ran = true;
gate.Release(); });
Assert.IsTrue(gate.WaitOne(TimeSpan.FromSeconds(2)));
Assert.IsTrue(ran);
}
[TestMethod]
public void EventLoop_DifferentThread()
{
var id = default(int);
var gate = new Semaphore(0, 1);
var el = new EventLoopScheduler();
el.Schedule(() =>
{
id = Thread.CurrentThread.ManagedThreadId;
gate.Release();
});
Assert.IsTrue(gate.WaitOne(TimeSpan.FromSeconds(2)));
Assert.AreNotEqual(Thread.CurrentThread.ManagedThreadId, id);
}
[TestMethod]
public void EventLoop_ScheduleOrderedActions()
{
var results = new List<int>();
var gate = new Semaphore(0, 1);
var el = new EventLoopScheduler();
el.Schedule(() => results.Add(0));
el.Schedule(() =>
{
results.Add(1);
gate.Release();
});
Assert.IsTrue(gate.WaitOne(TimeSpan.FromSeconds(2)));
results.AssertEqual(0, 1);
}
[TestMethod]
public void EventLoop_SchedulerDisposed()
{
var d = 0;
var e = new ManualResetEvent(false);
var f = new ManualResetEvent(false);
var results = new List<int>();
var el = new EventLoopScheduler();
el.Schedule(() => results.Add(0));
el.Schedule(() =>
{
el.Dispose();
e.Set();
results.Add(1);
try
{
el.Schedule(() => { throw new Exception("Should be disposed!"); });
f.Set();
}
catch (ObjectDisposedException)
{
// BREAKING CHANGE v2 > v1.x - New exception behavior.
Interlocked.Increment(ref d);
f.Set();
}
});
e.WaitOne();
try
{
el.Schedule(() => results.Add(2));
}
catch (ObjectDisposedException)
{
// BREAKING CHANGE v2 > v1.x - New exception behavior.
Interlocked.Increment(ref d);
}
f.WaitOne();
results.AssertEqual(0, 1);
Assert.AreEqual(2, d);
}
[TestMethod]
public void EventLoop_ScheduleTimeOrderedActions()
{
var results = new List<int>();
var gate = new Semaphore(0, 1);
var el = new EventLoopScheduler();
el.Schedule(TimeSpan.FromMilliseconds(50), () => results.Add(1));
el.Schedule(TimeSpan.FromMilliseconds(100), () =>
{
results.Add(0);
gate.Release();
});
Assert.IsTrue(gate.WaitOne(TimeSpan.FromSeconds(2)));
results.AssertEqual(1, 0);
}
[TestMethod]
public void EventLoop_ScheduleOrderedAndTimedActions()
{
var results = new List<int>();
var gate = new Semaphore(0, 1);
var el = new EventLoopScheduler();
el.Schedule(() => results.Add(1));
el.Schedule(TimeSpan.FromMilliseconds(100), () =>
{
results.Add(0);
gate.Release();
});
Assert.IsTrue(gate.WaitOne(TimeSpan.FromSeconds(2)));
results.AssertEqual(1, 0);
}
[TestMethod]
public void EventLoop_ScheduleTimeOrderedInFlightActions()
{
var results = new List<int>();
var gate = new Semaphore(0, 1);
var el = new EventLoopScheduler();
el.Schedule(TimeSpan.FromMilliseconds(100), () =>
{
results.Add(0);
el.Schedule(TimeSpan.FromMilliseconds(50), () => results.Add(1));
el.Schedule(TimeSpan.FromMilliseconds(100), ()=>
{
results.Add(2);
gate.Release();
});
});
Assert.IsTrue(gate.WaitOne(TimeSpan.FromSeconds(2)));
results.AssertEqual(0, 1, 2);
}
[TestMethod]
public void EventLoop_ScheduleTimeAndOrderedInFlightActions()
{
var results = new List<int>();
var gate = new Semaphore(0, 1);
var el = new EventLoopScheduler();
el.Schedule(TimeSpan.FromMilliseconds(100), () =>
{
results.Add(0);
el.Schedule(() => results.Add(4));
el.Schedule(TimeSpan.FromMilliseconds(50), () => results.Add(1));
el.Schedule(TimeSpan.FromMilliseconds(100), () =>
{
results.Add(2);
gate.Release();
});
});
Assert.IsTrue(gate.WaitOne(TimeSpan.FromSeconds(2)));
results.AssertEqual(0, 4, 1, 2);
}
[TestMethod]
public void EventLoop_ScheduleActionNested()
{
var ran = false;
var el = new EventLoopScheduler();
var gate = new Semaphore(0, 1);
el.Schedule(() => el.Schedule(() => { ran = true;
gate.Release(); }));
Assert.IsTrue(gate.WaitOne(TimeSpan.FromSeconds(2)));
Assert.IsTrue(ran);
}
#if !SILVERLIGHT
[TestMethod]
[Ignore]
public void EventLoop_ScheduleActionDue()
{
var ran = false;
var el = new EventLoopScheduler();
var sw = new Stopwatch();
var gate = new Semaphore(0, 1);
sw.Start();
el.Schedule(TimeSpan.FromSeconds(0.2), () => {
ran = true;
sw.Stop();
gate.Release();
});
Assert.IsTrue(gate.WaitOne(TimeSpan.FromSeconds(2)));
Assert.IsTrue(ran, "ran");
Assert.IsTrue(sw.ElapsedMilliseconds > 180, "due " + sw.ElapsedMilliseconds);
}
[TestMethod]
[Ignore]
public void EventLoop_ScheduleActionDueNested()
{
var ran = false;
var el = new EventLoopScheduler();
var gate = new Semaphore(0, 1);
var sw = new Stopwatch();
sw.Start();
el.Schedule(TimeSpan.FromSeconds(0.2), () =>
{
sw.Stop();
sw.Start();
el.Schedule(TimeSpan.FromSeconds(0.2), () =>
{
sw.Stop();
ran = true;
gate.Release();
});
});
Assert.IsTrue(gate.WaitOne(TimeSpan.FromSeconds(2)));
Assert.IsTrue(ran, "ran");
Assert.IsTrue(sw.ElapsedMilliseconds > 380, "due " + sw.ElapsedMilliseconds);
}
#endif
#if !NO_PERF
#if !NO_STOPWATCH
[TestMethod]
public void Stopwatch()
{
StopwatchTest.Run(new EventLoopScheduler());
}
#endif
#endif
#if !NO_CDS
[TestMethod]
public void EventLoop_Immediate()
{
var M = 1000;
var N = 4;
for (int i = 0; i < N; i++)
{
for (int j = 1; j <= M; j *= 10)
{
using (var e = new EventLoopScheduler())
{
var cd = new CountdownEvent(j);
for (int k = 0; k < j; k++)
e.Schedule(() => cd.Signal());
if (!cd.Wait(10000))
Assert.Fail("j = " + j);
}
}
}
}
[TestMethod]
public void EventLoop_TimeCollisions()
{
var M = 1000;
var N = 4;
for (int i = 0; i < N; i++)
{
for (int j = 1; j <= M; j *= 10)
{
using (var e = new EventLoopScheduler())
{
var cd = new CountdownEvent(j);
for (int k = 0; k < j; k++)
e.Schedule(TimeSpan.FromMilliseconds(100), () => cd.Signal());
if (!cd.Wait(10000))
Assert.Fail("j = " + j);
}
}
}
}
[TestMethod]
public void EventLoop_Spread()
{
var M = 1000;
var N = 4;
for (int i = 0; i < N; i++)
{
for (int j = 1; j <= M; j *= 10)
{
using (var e = new EventLoopScheduler())
{
var cd = new CountdownEvent(j);
for (int k = 0; k < j; k++)
e.Schedule(TimeSpan.FromMilliseconds(k), () => cd.Signal());
if (!cd.Wait(10000))
Assert.Fail("j = " + j);
}
}
}
}
#endif
[TestMethod]
public void EventLoop_Periodic()
{
var n = 0;
using (var s = new EventLoopScheduler())
{
var e = new ManualResetEvent(false);
var d = s.SchedulePeriodic(TimeSpan.FromMilliseconds(25), () =>
{
if (Interlocked.Increment(ref n) == 10)
e.Set();
});
if (!e.WaitOne(10000))
Assert.Fail();
d.Dispose();
}
}
#if STRESS
[TestMethod]
public void EventLoop_Stress()
{
EventLoop.NoSemaphoreFullException();
}
#endif
}
}

View File

@@ -0,0 +1,424 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive;
using System.Reactive.Concurrency;
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
namespace ReactiveTests.Tests
{
[TestClass]
public class HistoricalSchedulerTest
{
public DateTimeOffset Time(int i)
{
return new DateTimeOffset(1979, 10, 31, 4, 30, 15, TimeSpan.Zero).AddDays(i);
}
[TestMethod]
public void Ctor()
{
var s = new HistoricalScheduler();
Assert.AreEqual(DateTimeOffset.MinValue, s.Clock);
Assert.AreEqual(DateTimeOffset.MinValue, s.Now);
Assert.AreEqual(false, s.IsEnabled);
}
[TestMethod]
public void Start_Stop()
{
var s = new HistoricalScheduler();
var list = new List<Timestamped<int>>();
var ts = TimeSpan.FromHours(1);
s.Schedule(Time(0), () => list.Add(new Timestamped<int>(1, s.Now)));
s.Schedule(Time(1), () => list.Add(new Timestamped<int>(2, s.Now)));
s.Schedule(Time(2), () => s.Stop());
s.Schedule(Time(3), () => list.Add(new Timestamped<int>(3, s.Now)));
s.Schedule(Time(4), () => s.Stop());
s.Schedule(Time(5), () => s.Start());
s.Schedule(Time(6), () => list.Add(new Timestamped<int>(4, s.Now)));
s.Start();
Assert.AreEqual(Time(2), s.Now);
Assert.AreEqual(Time(2), s.Clock);
s.Start();
Assert.AreEqual(Time(4), s.Now);
Assert.AreEqual(Time(4), s.Clock);
s.Start();
Assert.AreEqual(Time(6), s.Now);
Assert.AreEqual(Time(6), s.Clock);
s.Start();
Assert.AreEqual(Time(6), s.Now);
Assert.AreEqual(Time(6), s.Clock);
list.AssertEqual(
new Timestamped<int>(1, Time(0)),
new Timestamped<int>(2, Time(1)),
new Timestamped<int>(3, Time(3)),
new Timestamped<int>(4, Time(6))
);
}
[TestMethod]
public void Order()
{
var s = new HistoricalScheduler();
var list = new List<Timestamped<int>>();
s.Schedule(Time(2), () => list.Add(new Timestamped<int>(2, s.Now)));
s.Schedule(Time(3), () => list.Add(new Timestamped<int>(3, s.Now)));
s.Schedule(Time(1), () => list.Add(new Timestamped<int>(0, s.Now)));
s.Schedule(Time(1), () => list.Add(new Timestamped<int>(1, s.Now)));
s.Start();
list.AssertEqual(
new Timestamped<int>(0, Time(1)),
new Timestamped<int>(1, Time(1)),
new Timestamped<int>(2, Time(2)),
new Timestamped<int>(3, Time(3))
);
}
[TestMethod]
public void Cancellation()
{
var s = new HistoricalScheduler();
var list = new List<Timestamped<int>>();
var d = s.Schedule(Time(2), () => list.Add(new Timestamped<int>(2, s.Now)));
s.Schedule(Time(1), () =>
{
list.Add(new Timestamped<int>(0, s.Now));
d.Dispose();
});
s.Start();
list.AssertEqual(
new Timestamped<int>(0, Time(1))
);
}
[TestMethod]
public void AdvanceTo_ArgumentChecking()
{
var now = DateTimeOffset.Now;
var s = new HistoricalScheduler(now);
ReactiveAssert.Throws<ArgumentOutOfRangeException>(() => s.AdvanceTo(now.Subtract(TimeSpan.FromSeconds(1))));
}
[TestMethod]
public void AdvanceTo()
{
var s = new HistoricalScheduler();
var list = new List<Timestamped<int>>();
s.Schedule(Time(0), () => list.Add(new Timestamped<int>(0, s.Now)));
s.Schedule(Time(1), () => list.Add(new Timestamped<int>(1, s.Now)));
s.Schedule(Time(2), () => list.Add(new Timestamped<int>(2, s.Now)));
s.Schedule(Time(10), () => list.Add(new Timestamped<int>(10, s.Now)));
s.Schedule(Time(11), () => list.Add(new Timestamped<int>(11, s.Now)));
s.AdvanceTo(Time(8));
Assert.AreEqual(Time(8), s.Now);
Assert.AreEqual(Time(8), s.Clock);
list.AssertEqual(
new Timestamped<int>(0, Time(0)),
new Timestamped<int>(1, Time(1)),
new Timestamped<int>(2, Time(2))
);
s.AdvanceTo(Time(8));
Assert.AreEqual(Time(8), s.Now);
Assert.AreEqual(Time(8), s.Clock);
list.AssertEqual(
new Timestamped<int>(0, Time(0)),
new Timestamped<int>(1, Time(1)),
new Timestamped<int>(2, Time(2))
);
s.Schedule(Time(7), () => list.Add(new Timestamped<int>(7, s.Now)));
s.Schedule(Time(8), () => list.Add(new Timestamped<int>(8, s.Now)));
ReactiveAssert.Throws<ArgumentOutOfRangeException>(() => s.AdvanceTo(Time(4)));
Assert.AreEqual(Time(8), s.Now);
Assert.AreEqual(Time(8), s.Clock);
list.AssertEqual(
new Timestamped<int>(0, Time(0)),
new Timestamped<int>(1, Time(1)),
new Timestamped<int>(2, Time(2))
);
s.AdvanceTo(Time(10));
Assert.AreEqual(Time(10), s.Now);
Assert.AreEqual(Time(10), s.Clock);
list.AssertEqual(
new Timestamped<int>(0, Time(0)),
new Timestamped<int>(1, Time(1)),
new Timestamped<int>(2, Time(2)),
new Timestamped<int>(7, Time(8)),
new Timestamped<int>(8, Time(8)),
new Timestamped<int>(10, Time(10))
);
s.AdvanceTo(Time(100));
Assert.AreEqual(Time(100), s.Now);
Assert.AreEqual(Time(100), s.Clock);
list.AssertEqual(
new Timestamped<int>(0, Time(0)),
new Timestamped<int>(1, Time(1)),
new Timestamped<int>(2, Time(2)),
new Timestamped<int>(7, Time(8)),
new Timestamped<int>(8, Time(8)),
new Timestamped<int>(10, Time(10)),
new Timestamped<int>(11, Time(11))
);
}
[TestMethod]
public void AdvanceBy_ArgumentChecking()
{
var s = new HistoricalScheduler();
ReactiveAssert.Throws<ArgumentOutOfRangeException>(() => s.AdvanceBy(TimeSpan.FromSeconds(-1)));
}
[TestMethod]
public void AdvanceBy()
{
var s = new HistoricalScheduler();
var list = new List<Timestamped<int>>();
s.Schedule(Time(0), () => list.Add(new Timestamped<int>(0, s.Now)));
s.Schedule(Time(1), () => list.Add(new Timestamped<int>(1, s.Now)));
s.Schedule(Time(2), () => list.Add(new Timestamped<int>(2, s.Now)));
s.Schedule(Time(10), () => list.Add(new Timestamped<int>(10, s.Now)));
s.Schedule(Time(11), () => list.Add(new Timestamped<int>(11, s.Now)));
s.AdvanceBy(Time(8) - s.Now);
Assert.AreEqual(Time(8), s.Now);
Assert.AreEqual(Time(8), s.Clock);
list.AssertEqual(
new Timestamped<int>(0, Time(0)),
new Timestamped<int>(1, Time(1)),
new Timestamped<int>(2, Time(2))
);
s.Schedule(Time(7), () => list.Add(new Timestamped<int>(7, s.Now)));
s.Schedule(Time(8), () => list.Add(new Timestamped<int>(8, s.Now)));
ReactiveAssert.Throws<ArgumentOutOfRangeException>(() => s.AdvanceBy(TimeSpan.FromDays(-4)));
Assert.AreEqual(Time(8), s.Now);
Assert.AreEqual(Time(8), s.Clock);
list.AssertEqual(
new Timestamped<int>(0, Time(0)),
new Timestamped<int>(1, Time(1)),
new Timestamped<int>(2, Time(2))
);
s.AdvanceBy(TimeSpan.Zero);
Assert.AreEqual(Time(8), s.Now);
Assert.AreEqual(Time(8), s.Clock);
list.AssertEqual(
new Timestamped<int>(0, Time(0)),
new Timestamped<int>(1, Time(1)),
new Timestamped<int>(2, Time(2))
);
s.AdvanceBy(TimeSpan.FromDays(2));
Assert.AreEqual(Time(10), s.Now);
Assert.AreEqual(Time(10), s.Clock);
list.AssertEqual(
new Timestamped<int>(0, Time(0)),
new Timestamped<int>(1, Time(1)),
new Timestamped<int>(2, Time(2)),
new Timestamped<int>(7, Time(8)),
new Timestamped<int>(8, Time(8)),
new Timestamped<int>(10, Time(10))
);
s.AdvanceBy(TimeSpan.FromDays(90));
Assert.AreEqual(Time(100), s.Now);
Assert.AreEqual(Time(100), s.Clock);
list.AssertEqual(
new Timestamped<int>(0, Time(0)),
new Timestamped<int>(1, Time(1)),
new Timestamped<int>(2, Time(2)),
new Timestamped<int>(7, Time(8)),
new Timestamped<int>(8, Time(8)),
new Timestamped<int>(10, Time(10)),
new Timestamped<int>(11, Time(11))
);
}
[TestMethod]
public void IsEnabled()
{
var s = new HistoricalScheduler();
Assert.AreEqual(false, s.IsEnabled);
s.Schedule(() =>
{
Assert.AreEqual(true, s.IsEnabled);
s.Stop();
Assert.AreEqual(false, s.IsEnabled);
});
Assert.AreEqual(false, s.IsEnabled);
s.Start();
Assert.AreEqual(false, s.IsEnabled);
}
[TestMethod]
public void No_Nested_AdvanceBy()
{
var s = new HistoricalScheduler();
s.Schedule(() => s.AdvanceBy(TimeSpan.FromSeconds(1)));
ReactiveAssert.Throws<InvalidOperationException>(() => s.Start());
}
[TestMethod]
public void No_Nested_AdvanceTo()
{
var s = new HistoricalScheduler();
s.Schedule(() => s.AdvanceTo(DateTimeOffset.Now.AddDays(1)));
ReactiveAssert.Throws<InvalidOperationException>(() => s.Start());
}
[TestMethod]
public void Sleep_ArgumentChecking()
{
var s = new HistoricalScheduler(DateTimeOffset.Now);
ReactiveAssert.Throws<ArgumentOutOfRangeException>(() => s.Sleep(TimeSpan.FromSeconds(-1)));
}
[TestMethod]
public void Sleep1()
{
var now = new DateTimeOffset(1983, 2, 11, 12, 0, 0, TimeSpan.Zero);
var s = new HistoricalScheduler(now);
s.Sleep(TimeSpan.FromDays(1));
Assert.AreEqual(now + TimeSpan.FromDays(1), s.Clock);
}
[TestMethod]
public void Sleep2()
{
var s = new HistoricalScheduler();
var n = 0;
s.Schedule(s.Now.AddMinutes(1), rec =>
{
s.Sleep(TimeSpan.FromMinutes(3));
n++;
rec(s.Now.AddMinutes(1));
});
s.AdvanceTo(s.Now + TimeSpan.FromMinutes(5));
Assert.AreEqual(2, n);
}
[TestMethod]
public void WithComparer_ArgumentChecking()
{
ReactiveAssert.Throws<ArgumentNullException>(() => new HistoricalScheduler(DateTimeOffset.Now, null));
}
[TestMethod]
public void WithComparer()
{
var now = DateTimeOffset.Now;
var s = new HistoricalScheduler(now, new ReverseComparer<DateTimeOffset>(Comparer<DateTimeOffset>.Default));
var res = new List<int>();
s.Schedule(now - TimeSpan.FromSeconds(1), () => res.Add(1));
s.Schedule(now - TimeSpan.FromSeconds(2), () => res.Add(2));
s.Start();
Assert.IsTrue(new[] { 1, 2 }.SequenceEqual(res));
}
class ReverseComparer<T> : IComparer<T>
{
private readonly IComparer<T> _comparer;
public ReverseComparer(IComparer<T> comparer)
{
_comparer = comparer;
}
public int Compare(T x, T y)
{
return -_comparer.Compare(x, y);
}
}
}
}

View File

@@ -0,0 +1,166 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using System;
using System.Diagnostics;
using System.Reactive.Concurrency;
using System.Reactive.Disposables;
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
namespace ReactiveTests.Tests
{
[TestClass]
public class ImmediateSchedulerTest
{
[TestMethod]
public void Immediate_Now()
{
var res = Scheduler.Immediate.Now - DateTime.Now;
Assert.IsTrue(res.Seconds < 1);
}
[TestMethod]
public void Immediate_ScheduleAction()
{
var id = Thread.CurrentThread.ManagedThreadId;
var ran = false;
Scheduler.Immediate.Schedule(() => { Assert.AreEqual(id, Thread.CurrentThread.ManagedThreadId); ran = true; });
Assert.IsTrue(ran);
}
[TestMethod]
public void Immediate_ScheduleActionError()
{
var ex = new Exception();
try
{
Scheduler.Immediate.Schedule(() => { throw ex; });
Assert.Fail();
}
catch (Exception e)
{
Assert.AreSame(e, ex);
}
}
[TestMethod]
public void Immediate_ArgumentChecking()
{
ReactiveAssert.Throws<ArgumentNullException>(() => Scheduler.Immediate.Schedule<int>(42, default(Func<IScheduler, int, IDisposable>)));
ReactiveAssert.Throws<ArgumentNullException>(() => Scheduler.Immediate.Schedule<int>(42, DateTimeOffset.Now, default(Func<IScheduler, int, IDisposable>)));
ReactiveAssert.Throws<ArgumentNullException>(() => Scheduler.Immediate.Schedule<int>(42, TimeSpan.Zero, default(Func<IScheduler, int, IDisposable>)));
}
[TestMethod]
public void Immediate_Simple1()
{
var _x = 0;
Scheduler.Immediate.Schedule<int>(42, (self, x) => { _x = x; return Disposable.Empty; });
Assert.AreEqual(42, _x);
}
[TestMethod]
public void Immediate_Simple2()
{
var _x = 0;
Scheduler.Immediate.Schedule<int>(42, DateTimeOffset.Now, (self, x) => { _x = x; return Disposable.Empty; });
Assert.AreEqual(42, _x);
}
[TestMethod]
public void Immediate_Simple3()
{
var _x = 0;
Scheduler.Immediate.Schedule<int>(42, TimeSpan.Zero, (self, x) => { _x = x; return Disposable.Empty; });
Assert.AreEqual(42, _x);
}
[TestMethod]
public void Immediate_Recursive1()
{
var _x = 0;
var _y = 0;
Scheduler.Immediate.Schedule<int>(42, (self, x) => { _x = x; return self.Schedule<int>(43, (self2, y) => { _y = y; return Disposable.Empty; }); });
Assert.AreEqual(42, _x);
Assert.AreEqual(43, _y);
}
[TestMethod]
public void Immediate_Recursive2()
{
var _x = 0;
var _y = 0;
Scheduler.Immediate.Schedule<int>(42, (self, x) => { _x = x; return self.Schedule<int>(43, DateTimeOffset.Now, (self2, y) => { _y = y; return Disposable.Empty; }); });
Assert.AreEqual(42, _x);
Assert.AreEqual(43, _y);
}
[TestMethod]
public void Immediate_Recursive3()
{
var _x = 0;
var _y = 0;
Scheduler.Immediate.Schedule<int>(42, (self, x) => { _x = x; return self.Schedule<int>(43, TimeSpan.FromMilliseconds(100), (self2, y) => { _y = y; return Disposable.Empty; }); });
Assert.AreEqual(42, _x);
Assert.AreEqual(43, _y);
}
[TestMethod]
public void Immediate_ArgumentChecking_More()
{
Scheduler.Immediate.Schedule(42, (self, state) =>
{
ReactiveAssert.Throws<ArgumentNullException>(() =>
{
self.Schedule(43, default(Func<IScheduler, int, IDisposable>));
});
return Disposable.Empty;
});
Scheduler.Immediate.Schedule(42, (self, state) =>
{
ReactiveAssert.Throws<ArgumentNullException>(() =>
{
self.Schedule(43, TimeSpan.FromSeconds(1), default(Func<IScheduler, int, IDisposable>));
});
return Disposable.Empty;
});
Scheduler.Immediate.Schedule(42, (self, state) =>
{
ReactiveAssert.Throws<ArgumentNullException>(() =>
{
self.Schedule(43, DateTimeOffset.UtcNow.AddDays(1), default(Func<IScheduler, int, IDisposable>));
});
return Disposable.Empty;
});
}
#if !SILVERLIGHT
[TestMethod]
[Ignore]
public void Immediate_ScheduleActionDue()
{
var id = Thread.CurrentThread.ManagedThreadId;
var ran = false;
var sw = new Stopwatch();
sw.Start();
Scheduler.Immediate.Schedule(TimeSpan.FromSeconds(0.2), () => { sw.Stop(); Assert.AreEqual(id, Thread.CurrentThread.ManagedThreadId); ran = true; });
Assert.IsTrue(ran, "ran");
Assert.IsTrue(sw.ElapsedMilliseconds > 180, "due " + sw.ElapsedMilliseconds);
}
#endif
}
}

View File

@@ -0,0 +1,125 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using System;
using System.Diagnostics;
using System.Reactive.Concurrency;
using System.Reactive.Disposables;
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
namespace ReactiveTests.Tests
{
[TestClass]
public class NewThreadSchedulerTest
{
[TestMethod]
public void NewThread_ArgumentChecking()
{
ReactiveAssert.Throws<ArgumentNullException>(() => new NewThreadScheduler(null));
ReactiveAssert.Throws<ArgumentNullException>(() => NewThreadScheduler.Default.Schedule<int>(42, default(Func<IScheduler, int, IDisposable>)));
ReactiveAssert.Throws<ArgumentNullException>(() => NewThreadScheduler.Default.Schedule<int>(42, DateTimeOffset.Now, default(Func<IScheduler, int, IDisposable>)));
ReactiveAssert.Throws<ArgumentNullException>(() => NewThreadScheduler.Default.Schedule<int>(42, TimeSpan.Zero, default(Func<IScheduler, int, IDisposable>)));
ReactiveAssert.Throws<ArgumentNullException>(() => NewThreadScheduler.Default.SchedulePeriodic<int>(42, TimeSpan.FromSeconds(1), default(Func<int, int>)));
ReactiveAssert.Throws<ArgumentNullException>(() => NewThreadScheduler.Default.ScheduleLongRunning<int>(42, default(Action<int, ICancelable>)));
ReactiveAssert.Throws<ArgumentOutOfRangeException>(() => NewThreadScheduler.Default.SchedulePeriodic<int>(42, TimeSpan.FromSeconds(-1), _ => _));
}
[TestMethod]
public void NewThread_Now()
{
var res = NewThreadScheduler.Default.Now - DateTime.Now;
Assert.IsTrue(res.Seconds < 1);
}
[TestMethod]
public void NewThread_ScheduleAction()
{
var id = Thread.CurrentThread.ManagedThreadId;
var nt = NewThreadScheduler.Default;
var evt = new ManualResetEvent(false);
nt.Schedule(() => { Assert.AreNotEqual(id, Thread.CurrentThread.ManagedThreadId); evt.Set(); });
evt.WaitOne();
}
#if !SILVERLIGHT
[TestMethod]
[Ignore]
public void NewThread_ScheduleActionDue()
{
var id = Thread.CurrentThread.ManagedThreadId;
var nt = NewThreadScheduler.Default;
var evt = new ManualResetEvent(false);
var sw = new Stopwatch();
sw.Start();
nt.Schedule(TimeSpan.FromSeconds(0.2), () => { sw.Stop(); Assert.AreNotEqual(id, Thread.CurrentThread.ManagedThreadId); evt.Set(); });
evt.WaitOne();
Assert.IsTrue(sw.ElapsedMilliseconds > 180, "due " + sw.ElapsedMilliseconds);
}
#endif
#if !NO_PERF
#if !NO_STOPWATCH
[TestMethod]
public void Stopwatch()
{
StopwatchTest.Run(NewThreadScheduler.Default);
}
#endif
#endif
[TestMethod]
public void NewThread_Periodic()
{
var n = 0;
var e = new ManualResetEvent(false);
var d = NewThreadScheduler.Default.SchedulePeriodic(TimeSpan.FromMilliseconds(25), () =>
{
if (Interlocked.Increment(ref n) == 10)
e.Set();
});
if (!e.WaitOne(10000))
Assert.Fail();
d.Dispose();
}
[TestMethod]
public void NewThread_Periodic_NonReentrant()
{
var n = 0;
var fail = false;
var d = NewThreadScheduler.Default.SchedulePeriodic(0, TimeSpan.FromMilliseconds(50), x =>
{
try
{
if (Interlocked.Increment(ref n) > 1) // Without an AsyncLock this would fail.
fail = true;
Thread.Sleep(100);
return x + 1;
}
finally
{
Interlocked.Decrement(ref n);
}
});
Thread.Sleep(500);
d.Dispose();
Assert.IsFalse(fail);
}
}
}

View File

@@ -0,0 +1,144 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Reactive.Concurrency;
using System.Reactive.Disposables;
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
namespace ReactiveTests
{
[TestClass]
public class ScheduledItemTest : ReactiveTest
{
[TestMethod]
public void ArgumentChecking()
{
ReactiveAssert.Throws<ArgumentNullException>(() => new ScheduledItem<DateTimeOffset, int>(default(IScheduler), 42, (x, y) => Disposable.Empty, DateTimeOffset.Now));
ReactiveAssert.Throws<ArgumentNullException>(() => new ScheduledItem<DateTimeOffset, int>(Scheduler.Default, 42, default(Func<IScheduler, int, IDisposable>), DateTimeOffset.Now));
ReactiveAssert.Throws<ArgumentNullException>(() => new ScheduledItem<DateTimeOffset, int>(default(IScheduler), 42, (x, y) => Disposable.Empty, DateTimeOffset.Now, Comparer<DateTimeOffset>.Default));
ReactiveAssert.Throws<ArgumentNullException>(() => new ScheduledItem<DateTimeOffset, int>(Scheduler.Default, 42, default(Func<IScheduler, int, IDisposable>), DateTimeOffset.Now, Comparer<DateTimeOffset>.Default));
ReactiveAssert.Throws<ArgumentNullException>(() => new ScheduledItem<DateTimeOffset, int>(Scheduler.Default, 42, (x, y) => Disposable.Empty, DateTimeOffset.Now, default(IComparer<DateTimeOffset>)));
}
[TestMethod]
public void Inequalities()
{
var si1 = new SI(42);
var si2 = new SI(43);
var si3 = new SI(42);
Assert.IsTrue(si1 < si2);
Assert.IsFalse(si1 < si3);
Assert.IsTrue(si1 <= si2);
Assert.IsTrue(si1 <= si3);
Assert.IsTrue(si2 > si1);
Assert.IsFalse(si3 > si1);
Assert.IsTrue(si2 >= si1);
Assert.IsTrue(si3 >= si1);
Assert.IsTrue(si1.CompareTo(si2) < 0);
Assert.IsTrue(si2.CompareTo(si1) > 0);
Assert.IsTrue(si1.CompareTo(si1) == 0);
Assert.IsTrue(si1.CompareTo(si3) == 0);
Assert.IsTrue(si2 > null);
Assert.IsTrue(si2 >= null);
Assert.IsFalse(si2 < null);
Assert.IsFalse(si2 <= null);
Assert.IsTrue(null < si1);
Assert.IsTrue(null <= si1);
Assert.IsFalse(null > si1);
Assert.IsFalse(null >= si1);
Assert.IsTrue(si1.CompareTo(null) > 0);
var si4 = new SI2(43, -1);
var si5 = new SI2(44, -1);
Assert.IsTrue(si4 > si1);
Assert.IsTrue(si4 >= si1);
Assert.IsTrue(si1 < si4);
Assert.IsTrue(si1 <= si4);
Assert.IsFalse(si4 > si2);
Assert.IsTrue(si4 >= si2);
Assert.IsFalse(si2 < si4);
Assert.IsTrue(si2 <= si4);
Assert.IsTrue(si5 > si4);
Assert.IsTrue(si5 >= si4);
Assert.IsFalse(si4 > si5);
Assert.IsFalse(si4 >= si5);
Assert.IsTrue(si4 < si5);
Assert.IsTrue(si4 <= si5);
Assert.IsFalse(si5 < si4);
Assert.IsFalse(si5 <= si4);
}
[TestMethod]
public void Equalities()
{
var si1 = new SI2(42, 123);
var si2 = new SI2(42, 123);
var si3 = new SI2(42, 321);
var si4 = new SI2(43, 123);
#pragma warning disable 1718
Assert.IsFalse(si1 != si1);
Assert.IsTrue(si1 == si1);
#pragma warning restore 1718
Assert.IsTrue(si1.Equals(si1));
Assert.IsTrue(si1 != si2);
Assert.IsFalse(si1 == si2);
Assert.IsFalse(si1.Equals(si2));
Assert.IsTrue(si1 != null);
Assert.IsTrue(null != si1);
Assert.IsFalse(si1 == null);
Assert.IsFalse(null == si1);
Assert.AreEqual(si1.GetHashCode(), si1.GetHashCode());
Assert.AreNotEqual(si1.GetHashCode(), si2.GetHashCode());
Assert.AreNotEqual(si1.GetHashCode(), si3.GetHashCode());
}
class SI : ScheduledItem<int>
{
public SI(int dueTime)
: base(dueTime, Comparer<int>.Default)
{
}
protected override IDisposable InvokeCore()
{
throw new NotImplementedException();
}
}
class SI2 : ScheduledItem<int>
{
private readonly int _value;
public SI2(int dueTime, int value)
: base(dueTime, Comparer<int>.Default)
{
_value = value;
}
protected override IDisposable InvokeCore()
{
throw new NotImplementedException();
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,48 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
#if !NO_STOPWATCH
using System;
using System.Reactive.Concurrency;
using System.Threading;
#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
namespace ReactiveTests.Tests
{
static class StopwatchTest
{
public static void Run(IStopwatchProvider stopwatchProvider)
{
/*
* TODO: Temporarily disabled until we iron out all of the scheduler improvements.
*/
//var N = 10;
//var t = default(long);
//var d = 1;
//for (int i = 0; i < N; i++)
//{
// var sw = stopwatchProvider.StartStopwatch();
// var e1 = sw.Elapsed;
// Thread.Sleep(d);
// var e2 = sw.Elapsed;
// Assert.IsTrue(e2.Ticks > e1.Ticks);
// t += (e2 - e1).Ticks;
// sw.Dispose();
//}
//Assert.IsTrue(TimeSpan.FromTicks(t / N).TotalMilliseconds < d * 10 /* 10x margin */);
}
}
}
#endif

View File

@@ -0,0 +1,241 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using System;
using System.Diagnostics;
using System.Reactive.Concurrency;
using System.Reactive.Disposables;
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
namespace ReactiveTests.Tests
{
[TestClass]
public class SynchronizationContextSchedulerTest
{
[TestMethod]
public void SynchronizationContext_ArgumentChecking()
{
var ms = new MySync();
var s = new SynchronizationContextScheduler(ms);
ReactiveAssert.Throws<ArgumentNullException>(() => new SynchronizationContextScheduler(null));
ReactiveAssert.Throws<ArgumentNullException>(() => new SynchronizationContextScheduler(null, true));
ReactiveAssert.Throws<ArgumentNullException>(() => s.Schedule<int>(42, default(Func<IScheduler, int, IDisposable>)));
ReactiveAssert.Throws<ArgumentNullException>(() => s.Schedule<int>(42, DateTimeOffset.Now, default(Func<IScheduler, int, IDisposable>)));
ReactiveAssert.Throws<ArgumentNullException>(() => s.Schedule<int>(42, TimeSpan.Zero, default(Func<IScheduler, int, IDisposable>)));
}
[TestMethod]
public void SynchronizationContext_Now()
{
var ms = new MySync();
var s = new SynchronizationContextScheduler(ms);
var res = s.Now - DateTime.Now;
Assert.IsTrue(res.Seconds < 1);
}
[TestMethod]
public void SynchronizationContext_ScheduleAction()
{
var ms = new MySync();
var s = new SynchronizationContextScheduler(ms);
var ran = false;
s.Schedule(() => { ran = true; });
Assert.IsTrue(ms.Count == 1);
Assert.IsTrue(ran);
}
[TestMethod]
public void SynchronizationContext_ScheduleAction_TimeSpan()
{
var ms = new MySync();
var s = new SynchronizationContextScheduler(ms);
var e = new ManualResetEvent(false);
s.Schedule(TimeSpan.FromMilliseconds(1), () => { e.Set(); });
e.WaitOne();
Assert.IsTrue(ms.Count == 1);
}
[TestMethod]
public void SynchronizationContext_ScheduleAction_DateTimeOffset()
{
var ms = new MySync();
var s = new SynchronizationContextScheduler(ms);
var e = new ManualResetEvent(false);
s.Schedule(DateTimeOffset.Now.AddMilliseconds(100), () => { e.Set(); });
e.WaitOne();
Assert.IsTrue(ms.Count >= 1); // Can be > 1 in case of timer queue retry operations.
}
[TestMethod]
public void SynchronizationContext_ScheduleActionError()
{
var ms = new MySync();
var s = new SynchronizationContextScheduler(ms);
var ex = new Exception();
try
{
s.Schedule(() => { throw ex; });
Assert.Fail();
}
catch (Exception e)
{
Assert.AreSame(e, ex);
}
Assert.IsTrue(ms.Count == 1);
}
#if !SILVERLIGHT
[TestMethod]
[Ignore]
public void SynchronizationContext_ScheduleActionDue()
{
var ms = new MySync();
var s = new SynchronizationContextScheduler(ms);
var evt = new ManualResetEvent(false);
var sw = new Stopwatch();
sw.Start();
s.Schedule(TimeSpan.FromSeconds(0.2), () => { sw.Stop(); evt.Set(); });
evt.WaitOne();
Assert.IsTrue(sw.ElapsedMilliseconds > 180, "due " + sw.ElapsedMilliseconds);
Assert.IsTrue(ms.Count == 1);
}
#endif
class MySync : SynchronizationContext
{
public int Count { get; private set; }
public override void Post(SendOrPostCallback d, object state)
{
Count++;
d(state);
}
public override void Send(SendOrPostCallback d, object state)
{
throw new NotImplementedException();
}
public int Started { get; private set; }
public override void OperationStarted()
{
base.OperationStarted();
Started++;
}
public int Completed { get; private set; }
public override void OperationCompleted()
{
base.OperationCompleted();
Completed++;
}
}
[TestMethod]
public void SynchronizationContext_StartedCompleted()
{
var ms = new MySync();
var s = new SynchronizationContextScheduler(ms);
var started = 0;
s.Schedule<int>(42, TimeSpan.Zero, (self, x) => { started = ms.Started; return Disposable.Empty; });
Assert.IsTrue(started == 1);
Assert.IsTrue(ms.Count == 1);
Assert.IsTrue(ms.Completed == 1);
}
[TestMethod]
public void SynchronizationContext_DontPost_Different()
{
var ms = new MySync();
var s = new SynchronizationContextScheduler(ms, false);
var ran = false;
s.Schedule(() => { ran = true; });
Assert.IsTrue(ms.Count == 1);
Assert.IsTrue(ran);
}
[TestMethod]
public void SynchronizationContext_DontPost_Same()
{
var count = 0;
var ran = false;
var t = new Thread(() =>
{
var ms = new MySync();
SynchronizationContext.SetSynchronizationContext(ms);
var s = new SynchronizationContextScheduler(ms, false);
s.Schedule(() => { ran = true; });
count = ms.Count;
});
t.Start();
t.Join();
Assert.IsTrue(count == 0 /* no post */);
Assert.IsTrue(ran);
}
[TestMethod]
public void SynchronizationContext_AlwaysPost_Different()
{
var ms = new MySync();
var s = new SynchronizationContextScheduler(ms, true);
var ran = false;
s.Schedule(() => { ran = true; });
Assert.IsTrue(ms.Count == 1);
Assert.IsTrue(ran);
}
[TestMethod]
public void SynchronizationContext_AlwaysPost_Same()
{
var count = 0;
var ran = false;
var t = new Thread(() =>
{
var ms = new MySync();
SynchronizationContext.SetSynchronizationContext(ms);
var s = new SynchronizationContextScheduler(ms, true);
s.Schedule(() => { ran = true; });
count = ms.Count;
});
t.Start();
t.Join();
Assert.IsTrue(count == 1 /* post */);
Assert.IsTrue(ran);
}
}
}

View File

@@ -0,0 +1,58 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using System;
using System.Reactive.Concurrency;
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 ReactiveTests.Dummies;
namespace ReactiveTests.Tests
{
[TestClass]
public class SynchronizationTests
{
[TestMethod]
public void Synchronization_SubscribeOn_ArgumentChecking()
{
ReactiveAssert.Throws<ArgumentNullException>(() => Synchronization.SubscribeOn(default(IObservable<int>), Scheduler.Immediate));
ReactiveAssert.Throws<ArgumentNullException>(() => Synchronization.SubscribeOn(DummyObservable<int>.Instance, default(IScheduler)));
#if !NO_SYNCCTX
ReactiveAssert.Throws<ArgumentNullException>(() => Synchronization.SubscribeOn(default(IObservable<int>), new MySyncCtx()));
ReactiveAssert.Throws<ArgumentNullException>(() => Synchronization.SubscribeOn(DummyObservable<int>.Instance, default(SynchronizationContext)));
#endif
}
[TestMethod]
public void Synchronization_ObserveOn_ArgumentChecking()
{
ReactiveAssert.Throws<ArgumentNullException>(() => Synchronization.ObserveOn(default(IObservable<int>), Scheduler.Immediate));
ReactiveAssert.Throws<ArgumentNullException>(() => Synchronization.ObserveOn(DummyObservable<int>.Instance, default(IScheduler)));
#if !NO_SYNCCTX
ReactiveAssert.Throws<ArgumentNullException>(() => Synchronization.ObserveOn(default(IObservable<int>), new MySyncCtx()));
ReactiveAssert.Throws<ArgumentNullException>(() => Synchronization.ObserveOn(DummyObservable<int>.Instance, default(SynchronizationContext)));
#endif
}
[TestMethod]
public void Synchronization_Synchronize_ArgumentChecking()
{
ReactiveAssert.Throws<ArgumentNullException>(() => Synchronization.Synchronize(default(IObservable<int>)));
ReactiveAssert.Throws<ArgumentNullException>(() => Synchronization.Synchronize(default(IObservable<int>), new object()));
ReactiveAssert.Throws<ArgumentNullException>(() => Synchronization.Synchronize(DummyObservable<int>.Instance, null));
}
class MySyncCtx : SynchronizationContext
{
}
}
}

View File

@@ -0,0 +1,172 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
#if !NO_TPL
using System;
using System.Reactive.Concurrency;
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
namespace ReactiveTests.Tests
{
[TestClass]
public class TaskPoolSchedulerTest
{
[TestMethod]
public void TaskPool_ArgumentChecking()
{
ReactiveAssert.Throws<ArgumentNullException>(() => new TaskPoolScheduler(null));
ReactiveAssert.Throws<ArgumentNullException>(() => TaskPoolScheduler.Default.Schedule<int>(42, default(Func<IScheduler, int, IDisposable>)));
ReactiveAssert.Throws<ArgumentNullException>(() => TaskPoolScheduler.Default.Schedule<int>(42, DateTimeOffset.Now, default(Func<IScheduler, int, IDisposable>)));
ReactiveAssert.Throws<ArgumentNullException>(() => TaskPoolScheduler.Default.Schedule<int>(42, TimeSpan.Zero, default(Func<IScheduler, int, IDisposable>)));
ReactiveAssert.Throws<ArgumentNullException>(() => TaskPoolScheduler.Default.SchedulePeriodic(42, TimeSpan.FromSeconds(1), default(Func<int, int>)));
ReactiveAssert.Throws<ArgumentOutOfRangeException>(() => TaskPoolScheduler.Default.SchedulePeriodic(42, TimeSpan.FromSeconds(-1), _ => _));
}
[TestMethod]
public void TaskPool_Now()
{
var res = TaskPoolScheduler.Default.Now - DateTime.Now;
Assert.IsTrue(res.Seconds < 1);
}
[TestMethod]
public void TaskPool_ScheduleAction()
{
var id = Thread.CurrentThread.ManagedThreadId;
var nt = TaskPoolScheduler.Default;
var evt = new ManualResetEvent(false);
nt.Schedule(() => { Assert.AreNotEqual(id, Thread.CurrentThread.ManagedThreadId); evt.Set(); });
evt.WaitOne();
}
[TestMethod]
public void TaskPool_ScheduleActionDueNow()
{
var id = Thread.CurrentThread.ManagedThreadId;
var nt = TaskPoolScheduler.Default;
var evt = new ManualResetEvent(false);
nt.Schedule(TimeSpan.Zero, () => { Assert.AreNotEqual(id, Thread.CurrentThread.ManagedThreadId); evt.Set(); });
evt.WaitOne();
}
[TestMethod]
public void TaskPool_ScheduleActionDue()
{
var id = Thread.CurrentThread.ManagedThreadId;
var nt = TaskPoolScheduler.Default;
var evt = new ManualResetEvent(false);
nt.Schedule(TimeSpan.FromMilliseconds(1), () => { Assert.AreNotEqual(id, Thread.CurrentThread.ManagedThreadId); evt.Set(); });
evt.WaitOne();
}
[TestMethod]
public void TaskPool_ScheduleActionCancel()
{
var id = Thread.CurrentThread.ManagedThreadId;
var nt = TaskPoolScheduler.Default;
var set = false;
var d = nt.Schedule(TimeSpan.FromSeconds(0.2), () => { Assert.Fail(); set = true; });
d.Dispose();
Thread.Sleep(400);
Assert.IsFalse(set);
}
#if !NO_PERF
[TestMethod]
public void TaskPool_ScheduleLongRunning()
{
var n = 0;
var e = new ManualResetEvent(false);
var gate = new object();
var d = TaskPoolScheduler.Default.ScheduleLongRunning(42, (x, cancel) =>
{
while (!cancel.IsDisposed)
lock (gate)
n++;
e.Set();
});
while (true)
{
lock (gate)
if (n >= 10)
break;
Thread.Sleep(10);
}
d.Dispose();
e.WaitOne();
Assert.IsTrue(n >= 0);
}
#endif
#if !NO_PERF
#if !NO_STOPWATCH
[TestMethod]
public void Stopwatch()
{
StopwatchTest.Run(TaskPoolScheduler.Default);
}
#endif
#endif
[TestMethod]
public void TaskPool_Periodic()
{
var n = 0;
var e = new ManualResetEvent(false);
var d = TaskPoolScheduler.Default.SchedulePeriodic(TimeSpan.FromMilliseconds(25), () =>
{
if (Interlocked.Increment(ref n) == 10)
e.Set();
});
if (!e.WaitOne(10000))
Assert.Fail();
d.Dispose();
}
[TestMethod]
public void TaskPool_Periodic_NonReentrant()
{
var n = 0;
var fail = false;
var d = TaskPoolScheduler.Default.SchedulePeriodic(0, TimeSpan.FromMilliseconds(50), x =>
{
try
{
if (Interlocked.Increment(ref n) > 1) // Without an AsyncLock this would fail.
fail = true;
Thread.Sleep(100);
return x + 1;
}
finally
{
Interlocked.Decrement(ref n);
}
});
Thread.Sleep(500);
d.Dispose();
Assert.IsFalse(fail);
}
}
}
#endif

View File

@@ -0,0 +1,329 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
#if !NO_THREAD
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Concurrency;
using System.Reactive.Disposables;
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
namespace ReactiveTests.Tests
{
[TestClass]
public class ThreadPoolSchedulerTest
{
[TestMethod]
public void Schedule_ArgumentChecking()
{
ReactiveAssert.Throws<ArgumentNullException>(() => ThreadPoolScheduler.Instance.Schedule<int>(42, default(Func<IScheduler, int, IDisposable>)));
ReactiveAssert.Throws<ArgumentNullException>(() => ThreadPoolScheduler.Instance.Schedule<int>(42, DateTimeOffset.Now, default(Func<IScheduler, int, IDisposable>)));
ReactiveAssert.Throws<ArgumentNullException>(() => ThreadPoolScheduler.Instance.Schedule<int>(42, TimeSpan.Zero, default(Func<IScheduler, int, IDisposable>)));
}
[TestMethod]
public void Get_Now()
{
var res = ThreadPoolScheduler.Instance.Now - DateTime.Now;
Assert.IsTrue(res.Seconds < 1);
}
[TestMethod]
public void ScheduleAction()
{
var id = Thread.CurrentThread.ManagedThreadId;
var nt = ThreadPoolScheduler.Instance;
var evt = new ManualResetEvent(false);
nt.Schedule(() => { Assert.AreNotEqual(id, Thread.CurrentThread.ManagedThreadId); evt.Set(); });
evt.WaitOne();
}
#if !NO_CDS
[TestMethod]
public void ProperRooting_NoGC_SingleShot()
{
var cts = new CancellationTokenSource();
new Thread(() =>
{
while (!cts.IsCancellationRequested)
{
Thread.Sleep(50);
GC.Collect();
GC.WaitForPendingFinalizers();
}
}).Start();
var tp = ThreadPoolScheduler.Instance;
var N = 100;
var cd = new CountdownEvent(N);
for (int i = 0; i < N; i++)
{
tp.Schedule(TimeSpan.FromMilliseconds(100 + i), () => { cd.Signal(); });
}
Assert.IsTrue(cd.Wait(TimeSpan.FromMinutes(1)));
cts.Cancel();
}
[TestMethod]
public void ProperRooting_NoGC_Periodic()
{
var cts = new CancellationTokenSource();
new Thread(() =>
{
while (!cts.IsCancellationRequested)
{
Thread.Sleep(50);
GC.Collect();
GC.WaitForPendingFinalizers();
}
}).Start();
var tp = ThreadPoolScheduler.Instance;
var N = 5;
var e = new ManualResetEvent(false);
var n = 0;
var d = tp.SchedulePeriodic(TimeSpan.FromMilliseconds(80), () => { if (Interlocked.Increment(ref n) == N) e.Set(); });
Assert.IsTrue(e.WaitOne(TimeSpan.FromMinutes(1)));
d.Dispose();
cts.Cancel();
}
#endif
#if !SILVERLIGHT
[TestMethod]
public void ScheduleActionDueRelative()
{
var id = Thread.CurrentThread.ManagedThreadId;
var nt = ThreadPoolScheduler.Instance;
var evt = new ManualResetEvent(false);
nt.Schedule(TimeSpan.FromSeconds(0.2), () => { Assert.AreNotEqual(id, Thread.CurrentThread.ManagedThreadId); evt.Set(); });
evt.WaitOne();
}
[TestMethod]
public void ScheduleActionDue0()
{
var id = Thread.CurrentThread.ManagedThreadId;
var nt = ThreadPoolScheduler.Instance;
var evt = new ManualResetEvent(false);
nt.Schedule(TimeSpan.FromTicks(0), () => { Assert.AreNotEqual(id, Thread.CurrentThread.ManagedThreadId); evt.Set(); });
evt.WaitOne();
}
[TestMethod]
public void ScheduleActionDueAbsolute()
{
var id = Thread.CurrentThread.ManagedThreadId;
var nt = ThreadPoolScheduler.Instance;
var evt = new ManualResetEvent(false);
nt.Schedule(DateTimeOffset.UtcNow + TimeSpan.FromSeconds(0.2), () => { Assert.AreNotEqual(id, Thread.CurrentThread.ManagedThreadId); evt.Set(); });
evt.WaitOne();
}
#endif
[TestMethod]
public void ScheduleActionCancel()
{
var id = Thread.CurrentThread.ManagedThreadId;
var nt = ThreadPoolScheduler.Instance;
var set = false;
var d = nt.Schedule(TimeSpan.FromSeconds(0.2), () => { Assert.Fail(); set = true; });
d.Dispose();
Thread.Sleep(400);
Assert.IsFalse(set);
}
#if !NO_PERF
[TestMethod]
public void ScheduleLongRunning_ArgumentChecking()
{
ReactiveAssert.Throws<ArgumentNullException>(() => ThreadPoolScheduler.Instance.ScheduleLongRunning<int>(42, default(Action<int, ICancelable>)));
}
[TestMethod]
public void ScheduleLongRunning()
{
var id = Thread.CurrentThread.ManagedThreadId;
var nt = ThreadPoolScheduler.Instance;
var evt = new ManualResetEvent(false);
nt.ScheduleLongRunning(42, (x, cancel) => { Assert.AreNotEqual(id, Thread.CurrentThread.ManagedThreadId); evt.Set(); });
evt.WaitOne();
}
[TestMethod]
public void ScheduleLongRunningCancel()
{
var nt = ThreadPoolScheduler.Instance;
var started = new ManualResetEvent(false);
var stopped = new ManualResetEvent(false);
var n = 0;
var d = nt.ScheduleLongRunning(42, (x, cancel) =>
{
for (n = 0; !cancel.IsDisposed; n++)
{
if (n == 10)
started.Set();
}
stopped.Set();
});
started.WaitOne();
d.Dispose();
stopped.WaitOne();
Assert.IsTrue(n >= 10);
}
#if !NO_STOPWATCH
[TestMethod]
public void Stopwatch()
{
var nt = ThreadPoolScheduler.Instance;
var sw = nt.StartStopwatch();
var s0 = sw.Elapsed.Ticks;
Thread.Sleep(10);
var s1 = sw.Elapsed.Ticks;
Assert.IsTrue(s1 > s0);
}
#endif
[TestMethod]
public void Periodic_ArgumentChecking()
{
ReactiveAssert.Throws<ArgumentNullException>(() => ThreadPoolScheduler.Instance.SchedulePeriodic(0, TimeSpan.FromSeconds(1), null));
ReactiveAssert.Throws<ArgumentOutOfRangeException>(() => ThreadPoolScheduler.Instance.SchedulePeriodic(0, TimeSpan.Zero, _ => _));
ReactiveAssert.Throws<ArgumentOutOfRangeException>(() => ThreadPoolScheduler.Instance.SchedulePeriodic(0, TimeSpan.FromSeconds(-1), _ => _));
}
[TestMethod]
public void Periodic_Regular()
{
var gate = new object();
var n = 0;
var e = new ManualResetEvent(false);
var lst = new List<int>();
var d = ThreadPoolScheduler.Instance.SchedulePeriodic(0, TimeSpan.FromMilliseconds(25), x =>
{
lock (gate)
{
if (n++ == 10)
e.Set();
}
lst.Add(x);
return x + 1;
});
e.WaitOne();
d.Dispose();
var m = default(int);
var k = default(int);
var i = 0;
do
{
lock (gate)
m = n;
Thread.Sleep(50);
lock (gate)
k = n;
} while (m != k && i++ < 10); // Wait for Dispose to reach the timer; should be almost instantaneous due to nop'ing out of the action.
Assert.AreNotEqual(10, i);
var res = lst.ToArray();
Assert.IsTrue(res.Length >= 10);
Assert.IsTrue(res.Take(10).SequenceEqual(Enumerable.Range(0, 10)));
}
[TestMethod]
public void Periodic_NonReentrant()
{
var n = 0;
var fail = false;
var d = ThreadPoolScheduler.Instance.SchedulePeriodic(0, TimeSpan.FromMilliseconds(50), x =>
{
try
{
if (Interlocked.Increment(ref n) > 1) // Without an AsyncLock this would fail.
fail = true;
Thread.Sleep(100);
return x + 1;
}
finally
{
Interlocked.Decrement(ref n);
}
});
Thread.Sleep(500);
d.Dispose();
Assert.IsFalse(fail);
}
#endif
#if DESKTOPCLR
[TestMethod]
public void No_ThreadPool_Starvation_Dispose()
{
var bwt = default(int);
var bio = default(int);
ThreadPool.GetAvailableThreads(out bwt, out bio);
var N = Environment.ProcessorCount * 2;
for (int i = 0; i < N; i++)
{
var e = new ManualResetEvent(false);
var f = new ManualResetEvent(false);
var d = ThreadPoolScheduler.Instance.Schedule(TimeSpan.FromMilliseconds(1), () => { e.Set(); f.WaitOne(); });
e.WaitOne();
d.Dispose();
f.Set();
}
var ewt = default(int);
var eio = default(int);
ThreadPool.GetAvailableThreads(out ewt, out eio);
Assert.IsFalse(bwt - ewt >= N);
}
#endif
}
}
#endif

View File

@@ -0,0 +1,134 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reactive.Concurrency;
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
namespace ReactiveTests.Tests
{
[TestClass]
public class VirtualSchedulerTest
{
class VirtualSchedulerTestScheduler : VirtualTimeScheduler<string, char>
{
public VirtualSchedulerTestScheduler()
{
}
public VirtualSchedulerTestScheduler(string initialClock, IComparer<string> comparer)
: base(initialClock, comparer)
{
}
protected override string Add(string absolute, char relative)
{
return (absolute ?? string.Empty) + relative;
}
protected override DateTimeOffset ToDateTimeOffset(string absolute)
{
return new DateTimeOffset((absolute ?? string.Empty).Length, TimeSpan.Zero);
}
protected override char ToRelative(TimeSpan timeSpan)
{
return (char)(timeSpan.Ticks % char.MaxValue);
}
}
[TestMethod]
public void Virtual_Now()
{
var res = new VirtualSchedulerTestScheduler().Now - DateTime.Now;
Assert.IsTrue(res.Seconds < 1);
}
[TestMethod]
public void Virtual_ScheduleAction()
{
var id = Thread.CurrentThread.ManagedThreadId;
var ran = false;
var scheduler = new VirtualSchedulerTestScheduler();
scheduler.Schedule(() => { Assert.AreEqual(id, Thread.CurrentThread.ManagedThreadId); ran = true; });
scheduler.Start();
Assert.IsTrue(ran);
}
[TestMethod]
public void Virtual_ScheduleActionError()
{
var ex = new Exception();
try
{
var scheduler = new VirtualSchedulerTestScheduler();
scheduler.Schedule(() => { throw ex; });
scheduler.Start();
Assert.Fail();
}
catch (Exception e)
{
Assert.AreSame(e, ex);
}
}
[TestMethod]
public void Virtual_InitialAndComparer_Now()
{
var s = new VirtualSchedulerTestScheduler("Bar", Comparer<string>.Default);
Assert.AreEqual(3, s.Now.Ticks);
}
[TestMethod]
public void Virtual_ArgumentChecking()
{
ReactiveAssert.Throws<ArgumentNullException>(() => new VirtualSchedulerTestScheduler("", null));
ReactiveAssert.Throws<ArgumentNullException>(() => new VirtualSchedulerTestScheduler().ScheduleRelative(0, 'a', null));
ReactiveAssert.Throws<ArgumentNullException>(() => new VirtualSchedulerTestScheduler().ScheduleAbsolute(0, "", null));
ReactiveAssert.Throws<ArgumentNullException>(() => new VirtualSchedulerTestScheduler().Schedule(0, default(Func<IScheduler, int, IDisposable>)));
ReactiveAssert.Throws<ArgumentNullException>(() => new VirtualSchedulerTestScheduler().Schedule(0, TimeSpan.Zero, default(Func<IScheduler, int, IDisposable>)));
ReactiveAssert.Throws<ArgumentNullException>(() => new VirtualSchedulerTestScheduler().Schedule(0, DateTimeOffset.UtcNow, default(Func<IScheduler, int, IDisposable>)));
ReactiveAssert.Throws<ArgumentNullException>(() => VirtualTimeSchedulerExtensions.ScheduleAbsolute(default(VirtualSchedulerTestScheduler), "", () => {}));
ReactiveAssert.Throws<ArgumentNullException>(() => VirtualTimeSchedulerExtensions.ScheduleAbsolute(new VirtualSchedulerTestScheduler(), "", default(Action)));
ReactiveAssert.Throws<ArgumentNullException>(() => VirtualTimeSchedulerExtensions.ScheduleRelative(default(VirtualSchedulerTestScheduler), 'a', () => { }));
ReactiveAssert.Throws<ArgumentNullException>(() => VirtualTimeSchedulerExtensions.ScheduleRelative(new VirtualSchedulerTestScheduler(), 'a', default(Action)));
}
[TestMethod]
public void Historical_ArgumentChecking()
{
ReactiveAssert.Throws<ArgumentNullException>(() => new HistoricalScheduler(DateTime.Now, default(IComparer<DateTimeOffset>)));
ReactiveAssert.Throws<ArgumentNullException>(() => new HistoricalScheduler().ScheduleAbsolute(42, DateTime.Now, default(Func<IScheduler, int, IDisposable>)));
ReactiveAssert.Throws<ArgumentNullException>(() => new HistoricalScheduler().ScheduleRelative(42, TimeSpan.FromSeconds(1), default(Func<IScheduler, int, IDisposable>)));
}
#if !SILVERLIGHT
[TestMethod]
[Ignore]
public void Virtual_ScheduleActionDue()
{
var id = Thread.CurrentThread.ManagedThreadId;
var ran = false;
var sw = new Stopwatch();
sw.Start();
var scheduler = new VirtualSchedulerTestScheduler();
scheduler.Schedule(TimeSpan.FromSeconds(0.2), () => { sw.Stop(); Assert.AreEqual(id, Thread.CurrentThread.ManagedThreadId); ran = true; });
scheduler.Start();
Assert.IsTrue(ran, "ran");
Assert.IsTrue(sw.ElapsedMilliseconds > 180, "due " + sw.ElapsedMilliseconds);
}
#endif
}
}