271 lines
7.9 KiB
C#
Raw Normal View History

// 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